2013-09-23 27 views
1

以下代碼使用後臺工作線程逐個處理工作項目。只要工作項目用完,工作線程就會開始等待ManualResetEvent。主線程定期添加新的工作項並喚醒工作線程。C#工作線程喚醒競爭條件

醒來機制有競爭條件。如果主線程添加新項目,而工作線程位於*指定的位置,則工作線程不會被喚醒。

是否有一種簡單且正確的方法來喚醒沒有此問題的工作線程?

ManualResetEvent m_waitEvent; 

    // Worker thread processes work items one by one 
    void WorkerThread() 
    { 
     while (true) 
     { 
      m_waitEvent.WaitOne(); 
      bool noMoreItems = ProcessOneWorkItem(); 
      if (noMoreItems) 
      { 
       // * 
       m_waitEvent.Reset(); // No more items, wait for more 
      } 
     } 
    } 

    // Main thread code that adds a new work item 
    AddWorkItem(); 
    m_waitEvent.Set(); // Wake worker thread 
+3

'System.Collections.Concurrent.ConcurrentQueue'' System.Collections.Concurrent.BlockingCollection' – I4V

回答

3

您正在使用錯誤的同步機制。而不是MRE只是使用信號量。信號量將代表尚未處理的項目數量。您可以將其設置爲添加一個,或者等待它減少一個。沒有if,你總是做每個信號量的行動,因此沒有競爭條件。

也就是說,你可以完全避免這個問題。您可以使用BlockingCollection而不是自己管理同步原語。生產者添加物品,消費者消費它們。所有同步都將由該類別爲您處理,並且可能比您的實現更有效。

0

我傾向於使用當前工作項目計數器並遞增和遞減該計數器。你可以把你的處理器線程變成一個循環,看着那個櫃檯然後睡覺,而不是一次運行完成。這樣,無論您何時添加物品,您都可以從正在處理的物品開始1個睡眠週期。