当一些WaitHandle正在调用WaitOne时,如何关闭应用程序?

时间:2010-06-21 19:11:15

标签: c# multithreading idisposable shutdown waithandle

是否有一种标准方法可以“干净地”关闭应用程序,而某些WaitHandle个对象可能处于对WaitOne的当前阻止调用状态?

例如,可能有一个后台线程在这样的方法中旋转:

while (_request.WaitOne())
{
    try
    {
        _workItem.Invoke();
    }
    finally
    {
        OnWorkCompleted();
    }
}

我没有看到没有明显的方法来处理这个线程而没有调用Thread.Abort(根据我所理解的不鼓励)。但是,在Close对象(_request)上调用AutoResetEvent会抛出异常。

目前,运行此循环的线程将IsBackground属性设置为true,因此应用程序出现以正确关闭。但是,由于WaitHandle实现了IDisposable,我不确定这是否被视为犹太洁食,或者是否应该在应用退出之前处理该对象。

这是一个糟糕的设计吗?如果没有,通常如何处理这种情况?

4 个答案:

答案 0 :(得分:8)

定义一个名为WaitHandle的额外_terminate,它会发出终止循环的请求,然后使用WaitHandle.WaitAny代替WaitHandle.WaitOne

var handles = { _request, _terminate };
while (WaitHandle.WaitAny(handles) == 0)
{
  try
  {
    _workItem.Invoke();
  }
  finally
  {
    OnCompleteWork();
  }
}

答案 1 :(得分:1)

IsBackground属性设置为true ...它会在您的应用结束时自动关闭该主题。

或者,您可以通过调用Thread.Interrupt来中断线程并处理ThreadInterruptedException。另一个想法是调用_request.Set()并使while循环检查volatile标志以确定应用程序是否正在关闭或是否应该继续:

private volatile bool _running = true;
while(_request.WaitOne() && _running)
{
    //...
}

// somewhere else in the app
_running = false;
_request.Set();

答案 2 :(得分:1)

当线程阻塞时(无论它阻塞什么)你可以调用Thread.Interrupt()这将导致异常ThreadInterruptedException(我相信,它可能会有所不同)你可以处理这个异常在线程本身并做任何必要的清理。

值得注意的是,线程只会在阻塞时抛出ThreadInterruptedException,如果它没有阻塞,则在下次尝试阻塞之前不会抛出它。

这是从我在这个主题上阅读的内容结束线程的“安全”方式。

还值得注意:如果对象同时实现了IDisposable和finializer(如果它使用非托管资源,它将会执行),GC将调用通常调用dispose的终结器。通常这是不确定的。但是,您几乎可以保证在应用程序退出时会调用它们。只有在非常特殊的情况下他们才会这样。 (抛出StackOverflowException之类的.net环境终止异常)

答案 3 :(得分:0)

我认为操作系统将在您的流程完成后进行清理。因为你的线程被标记为IsBackground,所以CLR将结束进程和所有线程,所以这不是问题。