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

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

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

我看不到没有打电话的情况下处理此线程的明显方法 Thread.Abort (据我所知,这是灰心的)。打电话 Close_request 对象(an AutoResetEvent)但是,将抛出一个例外。

目前,正在运行此循环的线程具有其 IsBackground 属性设置为 true, ,所以应用程序 出现 正确关闭。但是,自从 WaitHandle 工具 IDisposable, ,我不确定这是否被视为犹太洁食,还是该对象是否应该在应用程序退出之前被处置。

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

有帮助吗?

解决方案

定义另一个 WaitHandle_terminate 这将指示终止循环然后使用的请求 WaitHandle.WaitAny 代替 WaitHandle.WaitOne.

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

其他提示

当线程阻止时(不管它在什么阻塞上)时,您都可以致电 Thread.Interrupt() 这将导致例外 ThreadInterruptedException (我相信,这可能有些不同)您可以在线程本身上处理此例外,并进行任何必要的清理。

值得注意的是,线程只会抛出 ThreadInterruptedException 当它阻止时,如果不阻止它,直到下一步试图阻止它才会被抛弃。

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

还值得注意的是:如果对象同时实现IDISPOSABLE和FILIALISER(如果使用不受管理的资源,则将它们),GC将调用通常调用Dispose的最终化器。通常这是无确定性的。但是,您几乎可以保证他们会在申请退出时被要求。只有在非常特殊的情况下,他们不会。 (.NET环境终止例外,例如 StackOverflowException 被扔了)

设置 IsBackground 财产为 true...当您的应用结束时,它应该自动关闭线程。

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

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

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top