3

我有一个应用程序在队列中使用 AutoResetEvent (WaitOne/Set) 来处理消息。我注意到当我从 Visual Studio (Shift+F5) 终止调试会话时,应用程序的原始进程会挂起(但并非总是如此)。我手动将调试器重新附加到进程,并看到它有单个线程卡在 WaitHandle.WaitOne 上。

所以我的问题是,终止可能处于 WaitOne 状态的线程的正确方法是什么?

想到的第一个答案是听应用程序退出事件并在那里进行设置,但我不确定在这些调试会话之后是否可靠地调用了此事件,或者是否有我不知道的更标准的做法的。

而且,作为第二个问题,对于在“生产”模式下运行的应用程序,您会以不同的方式处理这个问题吗?

4

2 回答 2

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
    }
}

唯一的开销是在“一些”代码之后,您需要设置一个检查点以中止您的线程。希望这就是你要找的。

于 2012-11-30T13:41:21.320 回答
2

一种解决方案是使用该属性将线程设置为后台线程。Thread.IsBackground在线程上设置时,该线程不会停止退出进程。

但是,线程可能随时中断,通常会导致未定义的行为,具体取决于您的线程正在做什么。以我的拙见,终止线程的最佳方法是通知线程退出,例如通过设置退出标志并设置WaitHandle并唤醒它然后再Join调用线程。

于 2011-07-08T22:41:54.567 回答