关闭等待Windows服务中的计时器的线程

时间:2012-03-31 17:49:11

标签: c# multithreading .net-4.0 timer

我有一个.Net 4.0 C#Windows服务,它产生了许多连续运行的线程。每个线程基于计时器以不同的间隔运行。

我希望在服务关闭时正常关闭这些线程。

由于其中一些线程可能需要等待数小时来处理,我需要将它们唤醒并告诉它们退出。

我可以在这些线程中创建一个循环来定期检查一些全局变量,其间隔时间小于它们的处理间隔,但我更喜欢一种信号机制,它会导致定时器过早弹出。

如何在不使用Thread.Abort或Thread.Interrupt的情况下唤醒这些线程等待计时器?

3 个答案:

答案 0 :(得分:2)

我将假设您有充分的理由使用独立管理的线程来完成工作(而不是仅仅在计时器的事件中执行)。如果是这样,你想使用WaitHandle.WaitAny()并检查返回值以确定哪个WaitHandle导致线程继续:

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
        }
    }
}

答案 1 :(得分:2)

您可以使用WaitHandle.Waitone超时并使用事件

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

答案 2 :(得分:0)

根据您的情况,可能会选择使您生成后台线程的线程,这样您就不必担心明确关闭它们。

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

IsBackground设置为true会使生成的线程成为后台线程,不会阻止您的服务终止。

来自MSDN:

  

线程是后台线程或前台线程。   后台线程与前台线程相同,除此之外   后台线程不会阻止进程终止。一切都好   属于某个进程的前台线程已经终止,这是常见的   语言运行时结束进程。任何剩余的后台线程   停止了,没有完成。

这当然只是一个选项,如果你正在执行的任何操作可能被中断而不必优雅地关闭(例如做一些关键的清理工作)。否则,因为其他两个答案都建议您使用WaitHandle,并从主线程发出信号。