我有一个应用程序在队列中使用AutoResetEvent(WaitOne / Set)来处理消息。我注意到当我从Visual Studio(Shift + F5)终止调试会话时,应用程序的原始进程会挂起(但并非总是如此)。我手动将调试器重新附加到进程,并看到它在WaitHandle.WaitOne上有单线程。
所以我的问题是,终止可能处于WaitOne状态的线程的正确方法是什么?
首先想到的答案是听Application Exit事件并在那里做一个Set,但我不确定在这些调试会话之后是否可靠地调用了这个事件,或者我是否有更标准的练习我不知道。
而且,作为第二个问题,对于在“生产”模式下运行的应用程序,您会不同地处理这个问题吗?
答案 0 :(得分:4)
有一种简单的方法可以做到这一点(不是解决方法)
首先,您需要设置一个在您的应用程序即将死亡时将触发的事件
// somewhere with global scope. On a singleton or in program class maybe
// this is set when you want to terminate your application
private static ManualResetEvent ExitWaitHandle = new ManualResetEvent(false);
这是如何在别处使用它
// the event you want to check but it's blocking your application termination
private static AutoResetEvent yourEvent = new AutoResetEvent(true);
// the method where you have the problem
private static void FooAsync()
{
try
{
WaitHandle.WaitAny(new WaitHandle[]{yourEvent, ExitWaitHandle});
Checkpoint();
// other stuff here
// check if thread must die
Checkpoint();
}
catch(ApplicationTerminatingException)
{
// thread must die, do cleanup and finalization stuff here
}
catch(Exception)
{
// holy cow! what should we do?
}
}
private void CheckPoint()
{
// fast check if the exit handle is set
if(ExitWaitHandle.WaitOne(0))
{
throw new ApplicationTerminatingException(); // custom exception
}
}
唯一的开销是在“一些”代码之后你需要设置一个检查点以便中止你的线程。希望这是你想要的。
答案 1 :(得分:2)
一种解决方案是使用Thread.IsBackground
属性将线程设置为后台线程。在线程上设置时,该线程不会停止退出进程。
但是,线程可能会在任何时候中断,通常会导致未定义的行为,具体取决于您的线程正在做什么。以我的拙见终止线程的最好方法是通知线程退出,例如通过设置退出标志并设置WaitHandle
并将其唤醒然后Join
线程。