Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thread.Interrupt to stop long sleep at app shutdown - Is there a better approach

I'm having a small background thread which runs for the applications lifetime - however when the application is shutdown, the thread should exit gracefully.

The problem is that the thread runs some code at an interval of 15 minutes - which means it sleeps ALOT.

Now in order to get it out of sleep, I toss an interrupt at it - my question is however, if there's a better approach to this, since interrupts generate ThreadInterruptedException.

Here's the gist of my code (somewhat pseudo):

public class BackgroundUpdater : IDisposable
{
    private Thread myThread;
    private const int intervalTime = 900000; // 15 minutes
    public void Dispose()
    {
        myThread.Interrupt();
    }

    public void Start()
    {
        myThread = new Thread(ThreadedWork);
        myThread.IsBackground = true; // To ensure against app waiting for thread to exit
        myThread.Priority = ThreadPriority.BelowNormal;
        myThread.Start();
    }

    private void ThreadedWork()
    {
        try
        {
            while (true)
            {
                Thread.Sleep(900000); // 15 minutes
                DoWork();
            }
        }
        catch (ThreadInterruptedException)
        {
        }
    }
}
like image 385
Steffen Avatar asked Jul 17 '09 06:07

Steffen


People also ask

How do you stop a sleep thread?

interrupt() method: If any thread is in sleeping or waiting for a state then using the interrupt() method, we can interrupt the execution of that thread by showing InterruptedException. A thread that is in the sleeping or waiting state can be interrupted with the help of the interrupt() method of Thread class.

Why should a thread be interrupted?

An interrupt is an indication to a thread that it should stop what it is doing and do something else. It's up to the programmer to decide exactly how a thread responds to an interrupt, but it is very common for the thread to terminate.

What happens when thread is interrupted?

Interrupting a thread is a state-safe way to cancel it, but the thread itself has to be coded to pay attention to interrupts. Long, blocking Java operations that throw InterruptedException will throw that exception if an . interrupt() occurs while that thread is executing.

What happens if the current thread is interrupted by another thread in thread InterruptedException ()?

If any thread is in sleeping or waiting state (i.e. sleep() or wait() is invoked), calling the interrupt() method on the thread, breaks out the sleeping or waiting state throwing InterruptedException.


2 Answers

There's absolutely a better way - either use Monitor.Wait/Pulse instead of Sleep/Interrupt, or use an Auto/ManualResetEvent. (You'd probably want a ManualResetEvent in this case.)

Personally I'm a Wait/Pulse fan, probably due to it being like Java's wait()/notify() mechanism. However, there are definitely times where reset events are more useful.

Your code would look something like this:

private readonly object padlock = new object();
private volatile bool stopping = false;

public void Stop() // Could make this Dispose if you want
{
    stopping = true;
    lock (padlock)
    {
        Monitor.Pulse(padlock);
    }
}

private void ThreadedWork()
{
    while (!stopping)
    {
        DoWork();
        lock (padlock)
        {
            Monitor.Wait(padlock, TimeSpan.FromMinutes(15));
        }
    }
}

For more details, see my threading tutorial, in particular the pages on deadlocks, waiting and pulsing, the page on wait handles. Joe Albahari also has a tutorial which covers the same topics and compares them.

I haven't looked in detail yet, but I wouldn't be surprised if Parallel Extensions also had some functionality to make this easier.

like image 128
Jon Skeet Avatar answered Nov 30 '22 14:11

Jon Skeet


You could use an Event to Check if the Process should end like this:

var eventX = new AutoResetEvent(false);
while (true)
{
    if(eventX.WaitOne(900000, false))
    {
        break;
    }
    DoWork();
}
like image 24
frast Avatar answered Nov 30 '22 14:11

frast