views:

221

answers:

6

So I have a program that serves as a sort of 'shell' for other programs. At its core, it gets passed a class, a method name, and some args, and handles the execution of the function, with the idea of allowing other programmers to basically schedule their processes to run on this shell service. Everything works fine except for one issue. Frequently, these processes that are scheduled for execution are very CPU heavy. At times, the processes called start using so much of the CPU, that the threads that I have which are responsible for checking schedules and firing off other jobs don't get a chance to run for quite some time, resulting in scheduling issues and a lack of sufficient responsiveness. Unfortunately, I can't insert Thread.Sleep() calls in the actual running code, as I don't really 'own' it.

So my question is: Is it possible to force an arbitrary thread (that I started) to sleep (yield) every so often, without modifying the actual code running in that thread? Barring that, is there some way to 'inject' Thread.Sleep() calls into code that I'm about to run dynamically, at run-time?

+9  A: 

Not really. You could try changing the priority of the other thread with the Priority property, but you can't really inject a "sleep" call.

There's Thread.Suspend() but I strongly recommend you don't use it. You don't really want to get another thread to suspend at arbitrary times, as it might hold important resources. (That's why the method is marked as obsolete and has all kinds of warnings around it :)

Reducing the priority of the other tasks and potentially boosting the priority of your own tasks is probably the best approach.

Jon Skeet
I tried messing with the priority, but as far as I can gather, that affects how likely that thread is to 'win' the next available timeslice, but doesn't make it any more/less likely to 'yield' one itself. As to the resources issue, I suppose its possible, but each of these processes is supposed to be independant, to the extent that they're each run in seperate AppDomains. So the odds of two jobs wanting the same resource ought to be low (but non-zero).
GWLlosa
@GWLlosa: timeslices are sufficiently small that winning the next available one should be adequate for your scheduling thread to remain responsive. All you want is for that one to get priority over the tasks that are being run, which is exactly what it'll do.
jerryjvl
+3  A: 

No there is not (to my knowledge), you can however change the scheduling priority of a thread - http://msdn.microsoft.com/en-us/library/system.threading.thread.priority.aspx.

Lower the priority of the thread that is running the problem code as you start the thread (or raise the priority of your scheduling threads)

Kragen
+1, Bah, beat me to it.
Daniel Earwicker
+1  A: 

You can suspend a thread with Thread.Suspend (deprecated and not recommended) or you can lower its priority by changing Thread.Priority.

Remus Rusanu
A: 

If their classes had a virtual SleepIfNecessary() method, then I believe you could do override it by creating your own wrapper class through reflection.

But they would again be responsible for calling the method once in a while, during their loops.

[Edit]

I have never done something like this, but I don't see why you couldn't inject your own method call inside an existing one. (This link, for example: http://www.codeproject.com/KB/msil/reflexil.aspx)

Groo
A: 

Actually, what you are stating is very much a security risk and thus isn't going to be supported by most platforms. It's generally not a good policy to allow other programs to affect your status without your permission.

If possible, you could probably load the prog in question on its own process that you create in your code, and then you can set that processe's priority or make it sleep, or what have you. I am no expert in windows programming, so your mileage may vary.

San Jacinto
A: 

You should not be doing this. Threads should not Sleep() unless they themselves decide it's a good idea.

It's not relevant to your problem anyway. Your problem apparently is that management threads do not run, due to CPU starvation. To fix that, it's sufficient to give those threads a higher priority. At the end of each timeslice, the OS will determine which threads should run next. Thread priority is somewhat dynamic: threads that haven't run for a while will move up relative to threasd that just ran. But the higher base thread priority of your management threads will mean they don't need this dynamic boost to still get scheduled.

If this is still not sufficient, lower the priority of the worker threads. This will mean the worker thread has to be dormant for even more time before it gets a new timeslice.

Finally, make sure that the thread kicking off new worker threads runs at a very low priority. This will mean that no new threads are created if the system is hitting CPU limits. This implements a simple but robust throttling mechanism.

MSalters