Thread persists after application termination due to AutoResetEvent signal in WaitOne state
I have an application that uses an AutoResetEvent (WaitOne/Set) in a queue for processing messages. I'm noticing that when I terminate the a debug session from Visual Studio (Shift+F5) the original process for the application hangs around (but not always). I manually re-attach the debugger to the process, and see it has single thread stuck on WaitHandle.WaitOne.
So my question is, what is the correct way to terminate threads that may be in a WaitOne state?
The开发者_StackOverflow社区 first answer that sprang to mind was listen to the Application Exit event and doing a Set there, but I wasn't sure if this event was called reliably after these debug sessions, or if there is a more standard practice that I am not aware of.
And, as a second question, would you handle this differently for the application running in 'production' mode?
There is a simple way to do this (not a workaround)
First, you need to set an event that will fire when your application is going to die
// 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);
And this is how to use it elsewhere
// 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
}
}
The only overhead is that after "some" code you need to set a checkpoint in order to abort your thread. Hope this is what you were looking for.
One solution is to set the thread as background thread using the Thread.IsBackground
property. When set on a thread that thread will not stop a process for exiting.
However, the thread may be interrupted at any time usually leading to undefined behavior depending on what your thread is doing. The best way to terminate a thread in my humble opinion is to signal the thread to exit, e.g. by setting a quit flag and set the WaitHandle
and to wake it up then Join
ing the thread.
精彩评论