【问题标题】:Shutdown a thread waiting on a timer in a Windows Service关闭在 Windows 服务中等待计时器的线程
【发布时间】:2012-03-31 17:49:10
【问题描述】:

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

我想在服务关闭时优雅地关闭这些线程。

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

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

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

【问题讨论】:

  • 您不只是使用Timer 来完成工作(而不是使用计时器来锁定工作线程)的任何特殊原因?
  • 一个线程对于一个系统对象来说太昂贵了,除了等待几个小时之外什么都不做。您可以从 Timer 类中免费获得线程。
  • 这是一个现有的服务,目前有一个用于不同类型处理的线程。它目前使用 Thread.Abort() 和 Sleep。我将研究使用 Timer 及其产生的线程。

标签: c# multithreading .net-4.0 timer


【解决方案1】:

我将假设您有充分的理由使用独立管理的线程来完成工作(而不是仅在计时器事件中执行)。如果是这样,您想使用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
        }
    }
}

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      根据您的情况,您可以选择让线程生成后台线程,这样您就不必担心显式关闭它们。

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

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

      来自 MSDN:

      线程要么是后台线程,要么是前台线程。 后台线程与前台线程相同,除了 后台线程不会阻止进程终止。一旦所有 属于一个进程的前台线程已经终止,常见的 语言运行时结束该过程。任何剩余的后台线程 已停止且未完成。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-03
        • 2016-04-20
        • 1970-01-01
        • 2023-03-08
        • 1970-01-01
        • 2014-05-10
        相关资源
        最近更新 更多