8

WaitHandle一部のオブジェクトが への現在のブロッキング呼び出しの状態にある可能性がある間に、アプリケーションを「きれいに」閉じる標準的な方法はありWaitOneますか?

たとえば、次のようなメソッドでスピンしているバックグラウンド スレッドがある場合があります。

while (_request.WaitOne())
{
    try
    {
        _workItem.Invoke();
    }
    finally
    {
        OnWorkCompleted();
    }
}

呼び出しなしでこのスレッドを破棄する明確な方法Thread.Abortはありません (私が理解していることから、これはお勧めできません)。ただし、オブジェクト ( )を呼び出すCloseと、例外がスローされます。_requestAutoResetEvent

現在、このループを実行しているスレッドのIsBackgroundプロパティは に設定されてtrueいるため、アプリケーションは適切に閉じているように見えます。ただし、WaitHandle実装されているためIDisposable、これがコーシャと見なされるのか、アプリが終了する前にそのオブジェクトを本当に破棄する必要があるのか​​ はわかりません。

これはデザインが悪いのでしょうか?そうでない場合、このシナリオは通常どのように処理されますか?

4

4 に答える 4

8

ループを終了する要求を通知する追加のWaitHandle呼び出しを定義し、代わりに を使用します。_terminateWaitHandle.WaitAnyWaitHandle.WaitOne

var handles = { _request, _terminate };
while (WaitHandle.WaitAny(handles) == 0)
{
  try
  {
    _workItem.Invoke();
  }
  finally
  {
    OnCompleteWork();
  }
}
于 2010-06-21T19:37:12.017 に答える
1

スレッドがブロックされている場合 (何をブロックしているかに関係なく)、呼び出すことができますThread.Interrupt()。これにより、例外が発生しますThreadInterruptedException(少し異なる可能性があると思います)。スレッド自体でこの例外を処理し、必要なクリーンアップを行うことができます。

スレッドは、ThreadInterruptedExceptionブロックしているときにのみスローし、ブロックしていない場合は、次にブロックしようとするまでスローされないことに注意してください。

これは、私がこの件について読んだことから、スレッドを終了する「安全な」方法です。

また、注目に値する: オブジェクトが IDisposable とフィニヤライザー (アンマネージ リソースを使用する場合) の両方を実装する場合、GC は通常 dispose を呼び出すファイナライザーを呼び出します。通常、これは非決定論的です。ただし、アプリケーションの終了時に呼び出されることはほぼ保証できます。非常に特殊な状況下でのみ、そうはなりません。( などの .net 環境終了例外StackOverflowExceptionがスローされる)

于 2010-06-21T19:18:27.127 に答える
1

IsBackgroundプロパティを... に設定するtrueと、アプリの終了時にスレッドが自動的に閉じられます。

Thread.Interruptまたは、 を呼び出して処理することで、スレッドを中断できますThreadInterruptedException。もう 1 つのアイデアは_request.Set()、while ループを呼び出して volatile フラグをチェックさせ、アプリケーションが閉じているか、続行する必要があるかを判断することです。

private volatile bool _running = true;
while(_request.WaitOne() && _running)
{
    //...
}

// somewhere else in the app
_running = false;
_request.Set();
于 2010-06-21T19:14:08.790 に答える
0

プロセスが終了すると、オペレーティング システムがクリーンアップされると思います。スレッドが IsBackground としてマークされているため、CLR はプロセスとその中のすべてのスレッドを終了するため、これは問題ではありません。

于 2010-06-21T19:19:03.607 に答える