是否有一种标准方法可以“干净地”关闭应用程序,而某些WaitHandle
个对象可能处于对WaitOne
的当前阻止调用状态?
例如,可能有一个后台线程在这样的方法中旋转:
while (_request.WaitOne())
{
try
{
_workItem.Invoke();
}
finally
{
OnWorkCompleted();
}
}
我没有看到没有明显的方法来处理这个线程而没有调用Thread.Abort
(根据我所理解的不鼓励)。但是,在Close
对象(_request
)上调用AutoResetEvent
会抛出异常。
目前,运行此循环的线程将IsBackground
属性设置为true
,因此应用程序出现以正确关闭。但是,由于WaitHandle
实现了IDisposable
,我不确定这是否被视为犹太洁食,或者是否应该在应用退出之前处理该对象。
这是一个糟糕的设计吗?如果没有,通常如何处理这种情况?
答案 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将结束进程和所有线程,所以这不是问题。