1
votes

I have a .Net 4.0 C# Windows Service which spawns a number of thread which run continuously. Each thread runs at different intervals based on a timer.

I want to shut these threads down gracefully when the service is shutdown.

Since some of these threads may be waiting for hours to do it's processing, I need to wake them up and tell them to exit.

I could create a loop in these threads to periodically check some global variable at some interval less that their processing interval, but I would prefer a signaling mechanism which would cause them the timer to pop prematurely.

How can I wake these threads waiting on a timer without using Thread.Abort or Thread.Interrupt?

3
Any particular reason that you are not just using the Timer to do the work (as opposed to using the timer to latch the worker threads)? - Chris Shain
A thread is far too expensive a system object to be doing nothing useful but waiting for hours. You get the thread for free from the Timer class. - Hans Passant
It's an existing service which currently has a thread for different kinds of processing. It currently uses Thread.Abort() and Sleep. I will look into using Timer and the thread it spawns instead. - codezoo

3 Answers

2
votes

I'm going to assume that you have a good reason for using independently managed threads to do the work (as opposed to just doing it in the timer's event). If so, you want to use WaitHandle.WaitAny() and examine the return value to determine which WaitHandle caused the thread to proceed:

public class ExampleService
{
    private static readonly AutoResetEvent TimerLatch = new AutoResetEvent(false);
    private static readonly AutoResetEvent ShutdownLatch = new AutoResetEvent(false);
    private static readonly Timer MyTimer = new Timer(TimerTick);

    public void Start()
    {
        var t = new Thread(DoLoop);
        t.Start();

        MyTimer.Change(0, 500);
    }

    public void Stop()
    {
        ShutdownLatch.Set();
    }

    private static void TimerTick(object state)
    {
        TimerLatch.Set();
    }

    private static void DoLoop()
    {
        if (WaitHandle.WaitAny(new[] { TimerLatch, ShutdownLatch }) == 0)
        {
            // The timer ticked, do something timer related
        }
        else
        {
            // We are shutting down, do whatever cleanup you need
        }
    }
}
2
votes

You can use WaitHandle.Waitone with a timeout and use events

if (shutDownEvent.WaitOne(_timeout, false ))
{
   //Shutdown
}
else
{
   //timeout so Dowork
}
0
votes

Depending on your scenario it might be an option to make the threads you spawn background threads so you don't have to worry about explicitly shutting them down.

Thread thread = new Thread(DoSomething)
{
        IsBackground = true
};

Setting IsBackground to true makes the spawned thread a background thread which won't stop your service from terminating.

From MSDN:

A thread is either a background thread or a foreground thread. Background threads are identical to foreground threads, except that background threads do not prevent a process from terminating. Once all foreground threads belonging to a process have terminated, the common language runtime ends the process. Any remaining background threads are stopped and do not complete.

This of course is only an option if whatever operation you are performing may be interrupted and don't have to gracefully shut down (e.g. do some critical cleanup work). Otherwise as both other answers are suggesting you should use a WaitHandle, and signal from the main thread.