当某些Waithandle在Waitone的电话中间,您如何关闭应用程序?
-
28-09-2019 - |
题
是否有一种标准方法可以“干净地”关闭应用程序时 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将结束过程和所有线程,因此这不是问题。