0

私は現在、単一のスレッドに対してManualResetEventを使用して、複数のスレッドがスレッドマネージャーのキューに何かを追加するのを待機しています。スレッドマネージャーが手動リセットイベントを使用してシグナルを受信すると、追加されたアイテムをデキューし、さらに処理を行います。私の唯一の問題は、複数のセットがトリガーされた場合、他のキューアイテムが処理されないことです。(ポイントBを参照)

while (IsThreadRunning)
{
    // A: My workaround is to check if queue has item, if not then wait for other thread to set the event
    if (DataQueue.Count <= 0)
    {
        ResetEvent.WaitOne();
    }

    // B: At this point two thread added item to the queue and did ResetEvent.Set() twice.
    if (DataQueue.Count > 0)
    {
        DataQueue.Dequeue();
    }

    // Reset the event to avoid processor hog
    ResetEvent.Reset();
}

ここでの私の回避策は、ポイントAにキューサイズ条件を追加することです。デッドロックを回避するためにこれを実行する別の方法はありますか?

注:ManualResetEventの使用例で示されている通常のシナリオでは、単一のスレッドでイベントを待機している複数のスレッド(ManualResetEvent.Wait)がありますが、ここでは複数のスレッドがイベントをトリガーします(ManualResetEvent.Set)。このシナリオで使用される他のクラスはありますか?

4

2 に答える 2

1

キュー内のすべてのアイテムを処理し、イベントが通知されるのを待つことができます。

イベントが通知されたら、すぐにリセットします。

キュー内の最後のアイテムを処理した後にイベントが通知された場合、最悪の事態は、キューをチェックして空になることです。

while (IsThreadRunning)
{
  while ( DataQueue.Count > 0 )
  {
    DataQueue.Dequeue();
  }
  ResetEvent.WaitOne();
  ResetEvent.Reset();
}
于 2012-02-28T01:41:15.797 に答える
1

手動リセット イベントを今すぐダンプします。これには、いかなる種類のイベントも使用しないでください。セマフォとロックを使用します。push メソッドでは、キューをロックし、オブジェクトをキューにプッシュし、lock ステートメント ブロックを終了してから、セマフォにシグナルを送ります。pop メソッドでは、セマフォで待機してから、キューでロックし、オブジェクトをポップしてロック ステートメント ブロックを終了します。

これは、プロデューサーとコンシューマーのキューを自作したい場合です。すでに機能しているキューが必要な場合は、BlockingCollection クラスを参照してください。

于 2012-02-28T01:43:25.703 に答える