我有一个.Net 4.0 C#Windows服务,它产生了许多连续运行的线程。每个线程基于计时器以不同的间隔运行。
我希望在服务关闭时正常关闭这些线程。
由于其中一些线程可能需要等待数小时来处理,我需要将它们唤醒并告诉它们退出。
我可以在这些线程中创建一个循环来定期检查一些全局变量,其间隔时间小于它们的处理间隔,但我更喜欢一种信号机制,它会导致定时器过早弹出。
如何在不使用Thread.Abort或Thread.Interrupt的情况下唤醒这些线程等待计时器?
答案 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
,并从主线程发出信号。