Thread.Interrupt在应用程序关闭时停止长时间睡眠 - 是否有更好的方法

Ste*_*fen 5 c# multithreading interrupt

我有一个小的后台线程,它运行应用程序的生命周期 - 但是当应用程序关闭时,线程应该优雅地退出.

问题是该线程以15分钟的间隔运行一些代码 - 这意味着它会睡眠很多.

现在为了让它从睡眠状态中解脱出来,我会向它抛出一个中断 - 但我的问题是,如果有一个更好的方法,因为中断会产生ThreadInterruptedException.

这是我的代码的要点(有点伪):

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)
        {
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 14

绝对有更好的方法 - 使用Monitor.Wait/ Pulse而不是Sleep/Interrupt,或者使用Auto/ ManualResetEvent.(ManualResetEvent在这种情况下你可能想要一个.)

就个人而言,我是Wait/Pulse的粉丝,可能是因为它像Java的wait()/ notify()机制.但是,有时候重置事件更有用.

您的代码看起来像这样:

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));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

有关更多详细信息,请参阅我的线程教程,特别是关于死锁,等待和脉冲的页面,等待句柄上的页面.Joe Albahari 还有一个教程,涵盖相同的主题并进行比较.

我还没有详细介绍过,但如果Parallel Extensions还有一些功能可以让我更容易,我也不会感到惊讶.

  • 这里的问题不是工作线程在持有锁时等待,所以stop()方法中的锁定会阻塞最多15分钟,直到工作线程释放锁定? (2认同)
  • @Svish - Joe Albahari的教程很好地解释了这一点 - "等待"实际上在等待脉冲时解锁对象.我发现这种模式对那些不熟悉这种"等待"行为的人来说是不可读的. (2认同)