12

以下は、私の問題を示すメソッド「SomeMethod」を持つクラスです。

class SomeClass
{
    AutoResetEvent theEvent = new AutoResetEvent(false);
    // more member declarations

    public void SomeMethod()
    {
        // some code
        theEvent.WaitOne();
        // more code
    }
}

このメソッドはスレッドセーフになるように設計されており、異なるスレッドで呼び出されます。ここで私の質問は、いつでも「theEvent」オブジェクトで「WaitOne」メソッドを呼び出したすべてのスレッドのブロックを解除する方法です。マルチスレッド プログラムを正常に停止および開始できるようにする必要があるため、この要件は私の設計で頻繁に発生します。マルチスレッド プログラムを開始するのはかなり簡単ですが、停止するのは難しいように思えます。

これが私がこれまでに試したもので、明らかにうまくいきます。しかし、これは標準的なアプローチですか?

public void UnblockAll()
{
    do
    {
        theEvent.Set();
    } while (theEvent.WaitOne(0));
}

「UnblockAll」メソッドは、「SomeClass」クラスのメンバーです。ここで使用する手法は、WaitOne メソッドの MSDN ドキュメントに基づいています。以下のドキュメントの関連部分を引用しています。

millisecondsTimeout がゼロの場合、メソッドはブロックされません。待機ハンドルの状態をテストし、すぐに戻ります。

do..while ループでSet メソッドを呼び出します。これにより、WaitOne メソッド (「SomeMethod」メソッド内にコード化されている) への呼び出しが原因でブロックされた可能性がある単一のスレッドが解放されます。次に、'theEvent' オブジェクトの状態をテストして、シグナル状態かどうかを確認します。このテストは、タイムアウト パラメータを受け取る WaitOne メソッドのオーバーロードされたバージョンを呼び出すことによって行われます。WaitOne メソッドを呼び出すときに使用する引数はゼロです。ドキュメントによると、呼び出しはブール値ですぐに返されます。戻り値が true の場合、「theEvent」オブジェクトシグナル状態です。「SomeMethod」メソッドの「WaitOne」メソッドの呼び出しで少なくとも 1 つのスレッドがブロックされていた場合、「Set」メソッド (「UnblockAll」メソッド内にコード化されている) の呼び出しによってブロックが解除されます。したがって、'UnblockAll' メソッドの do..while ステートメントの最後にある 'WaitOne' メソッドの呼び出しは false を返します。ブロックされたスレッドがない場合にのみ、戻り値は true になります。

上記の推論は正しいですか? また、正しい場合、その手法は私の問題に対処するための標準的な方法ですか? 主に .net コンパクト フレームワーク 2.0 プラットフォームでソリューションを使用しようとしています。

4

3 に答える 3

11

3 つの実行可能なオプションがあります。それぞれに独自の長所と短所があります。特定の状況に最も適したものを選択してください。

オプション 1 - をポーリングしWaitHandleます。

無期限のブロック呼び出しを行う代わりに、タイムアウト付きの呼び出しを使用し、シャットダウン要求が与えられていない場合はブロックを元に戻します。

public void SomeMethod()
{
  while (!yourEvent.WaitOne(POLLING_INTERVAL))
  {
    if (IsShutdownRequested())
    {
      // Add code to end gracefully here.
    }
  }
  // Your event was signaled so now we can proceed.
}

オプション 2 -WaitHandleシャットダウンを要求するために別のを使用する

public void SomeMethod()
{
  WaitHandle[] handles = new WaitHandle[] { yourEvent, shutdownEvent };
  if (WaitHandle.WaitAny(handles) == 1)
  {
    // Add code to end gracefully here.
  }
  // Your event was signaled so now we can proceed.
}

オプション 3 - 使用Thread.Interrupt

と混同しないでくださいThread.Abort。スレッドを中止することは間違いなく安全ではありませんが、スレッドを中断することはまったく異なります。、、などThread.Interruptを含む BCL で使用される組み込みのブロッキング呼び出しを「突く」 。Thread.JoinWaitHandle.WaitOneThread.Sleep

于 2011-05-09T17:49:49.070 に答える
1

スレッドアボートはフレームワークで機能しますか?

于 2011-05-09T17:34:12.740 に答える