Interrupt a sleeping Thread
You can use Thead.Interrupt to wake a sleeping thread. It will cause a ThreadInteruptedException
on the blocked thread, so it's not the most elegant or efficient approach.
You also need to be weary that interrupting a thread in this way is unsafe. It does not provide control over the point at which the thread is aborted, and therefore should not be used without careful consideration as to the consequences. As mentioned in other answers already, it's is far better to use signal based techniques to control when the thread terminates in a controlled manner.
Instead of using Thread.Sleep
use ManualResetEvent.WaitOne
.
while (true) {
if(DateTime.Now.Subtract(_lastExecuteTime).TotalHours > 1) {
DoWork();
_lastExecuteTime = DateTime.Now();
continue;
}
if (terminate.WaitOne(10000)) {
break;
}
}
Where terminate
is a ManualResetEvent
1 that you can Set
to request termination of the loop.
Update:
I just noticed that you said you are already using ManualResetEvent
to terminate the background work (I am assuming that is in DoWork
). Is there any reason why you cannot use the same MRE? If that is not possible there certainly should not be an issue using a different one.
Update 2:
Yeah, so instead of Thread.Sleep(5000)
in ExecuteWorker
do _shutdownEvent.WaitOne(5000)
instead. It would look like the following.
private void ExecuteWorker() {
while (true) {
_pauseEvent.WaitOne(Timeout.Infinite);
//This kills our process
if (_shutdownEvent.WaitOne(0)) {
break;
}
if (!_worker.IsReadyToExecute) {
//sleep 5 seconds before checking again. If we go any longer we keep our service from shutting down when it needs to.
_shutdownEvent.WaitOne(5000);
continue;
}
DoWork();
}
}
1There is also a ManualResetEventSlim
class in .NET 4.0.
Instead of using Thread.Sleep
, you can use Monitor.Wait
with a timeout - and then you can use Monitor.Pulse
from a different thread to wake it up.
Don't forget you'll need to lock on the monitor before calling either Wait
or Pulse
:
// In the background thread
lock (monitor)
{
// If we've already been told to quit, we don't want to sleep!
if (somethingIndicatingQuit)
{
break;
}
Monitor.Wait(monitor, TimeSpan.FromSeconds(10));
if (somethingIndicatingQuit)
{
break;
}
}
// To wake it up...
lock (monitor)
{
somethingIndicatingQuit = true;
Monitor.Pulse(monitor);
}