2012-02-28 1 views
1

私は現在、単一のスレッドに対して複数のスレッドが何かをスレッドマネージャのキューに追加するのを待つためにManualResetEventを使用しています。スレッドマネージャが手動リセットイベントを使用して信号を受信すると、スレッドマネージャは追加されたアイテムをデキューし、さらに処理を行います。私の唯一の問題は、複数のセットがトリガーされている場合、他のキューアイテムは処理されないということです。ManualResetEventのサイズは、複数のスレッドを待機するのに十分なチェックですか?

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(); 
} 

点Bを参照)、ここに私の問題を回避するには、ポイント上のキューサイズの条件を追加することです。 これを実行してデッドロックを回避する別の方法はありますか?

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

+1

ちょっと変えてみてはいかがですか? –

答えて

1

キュー内のすべてのアイテムを処理できます(存在する場合)。イベントが通知されるのを待ちます。

イベントが通知されるとすぐにリセットします。

最後にキュー内のアイテムを処理した後にイベントが通知されると、キューがチェックされて空になります。

while (IsThreadRunning) 
{ 
    while (DataQueue.Count > 0) 
    { 
    DataQueue.Dequeue(); 
    } 
    ResetEvent.WaitOne(); 
    ResetEvent.Reset(); 
} 
1

ここで手動リセットイベントをダンプします。これにはどんな種類のイベントも使用しないでください。セマフォとロックを使用します。プッシュメソッドでは、キューをロックし、オブジェクトをキューにプッシュし、ロックステートメントブロックを終了してからセマフォを通知します。 popメソッドでは、セマフォを待ち、キューをロックし、オブジェクトをポップオフしてlock文ブロックを終了します。

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

+0

これはあなたのものですか? http://www.dijksterhuis.org/using-semaphores-in-c/ – Nap

+0

@Nap - no。キュー・ロックとセマフォを使用すると(キューがバインドされている場合は2セマフォ)、プロデューサ/コンシューマ・キューを実装するための 'Computer Science 101'の方法です。私は、開発者がセマフォの代わりにイベントを使用してカウンタを持つ同期メカニズムのために叫ぶ何かのアイディアを得るのか分からない! –

関連する問題