3

メッセージを処理するキューで AutoResetEvent (WaitOne/Set) を使用するアプリケーションがあります。Visual Studio (Shift + F5) からデバッグ セッションを終了すると、アプリケーションの元のプロセスがハングアップすることに気付きました (常にではありません)。手動でデバッガーをプロセスに再接続すると、単一のスレッドが WaitHandle.WaitOne で停止していることがわかります。

だから私の質問は、WaitOne 状態にある可能性のあるスレッドを終了する正しい方法は何ですか?

頭に浮かんだ最初の答えは、Application Exit イベントをリッスンし、そこで Set を実行することでしたが、これらのデバッグ セッションの後にこのイベントが確実に呼び出されたのか、それとも私が認識していないより標準的な方法があるのか​​はわかりませんでした。の。

そして、2 番目の質問として、「プロダクション」モードで実行されているアプリケーションでは、これを別の方法で処理しますか?

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

1 つの解決策は、プロパティを使用してスレッドをバックグラウンド スレッドとして設定することです。Thread.IsBackgroundスレッドに設定すると、そのスレッドは終了のためにプロセスを停止しません。

ただし、スレッドはいつでも中断される可能性があり、通常、スレッドの実行内容によっては未定義の動作が発生します。私の謙虚な意見では、スレッドを終了する最善の方法は、終了フラグを設定してスレッドを起動し、スレッドを起動するなど、スレッドに終了を通知するWaitHandleことJoinです。

于 2011-07-08T22:41:54.567 に答える