C#工作线程唤醒竞态条件

C#工作线程唤醒竞态条件,c#,multithreading,race-condition,C#,Multithreading,Race Condition,下面的代码使用后台工作线程逐个处理工作项。每当工作线程用完工作项时,它就会开始等待ManualResetEvent。主线程定期添加新的工作项并唤醒工作线程 唤醒机制具有竞争条件。如果主线程在工作线程位于*指示的位置时添加了新项目,则工作线程将不会被唤醒 是否有一种简单而正确的方法来唤醒没有此问题的工作线程 ManualResetEvent m_waitEvent; // Worker thread processes work items one by one void

下面的代码使用后台工作线程逐个处理工作项。每当工作线程用完工作项时,它就会开始等待ManualResetEvent。主线程定期添加新的工作项并唤醒工作线程

唤醒机制具有竞争条件。如果主线程在工作线程位于*指示的位置时添加了新项目,则工作线程将不会被唤醒

是否有一种简单而正确的方法来唤醒没有此问题的工作线程

    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

我倾向于使用当前工作项计数器,并递增和递减该计数器。您可以将处理器线程转换为一个循环,该循环正在查看该计数器,然后进入休眠状态,而不是只运行一次就完成。这样,无论添加项目时您在何处,您都将从正在处理的项目开始1个睡眠周期。

您使用了错误的同步机制。与其使用MRE,不如使用信号量。然后,信号量将表示尚未处理的项目数。您可以将其设置为添加一个,或等待它将其减少一个。没有
,如果
,您总是执行每个信号量操作,因此不存在争用条件


也就是说,你可以完全避免这个问题。您可以使用
BlockingCollection
,而不是自己管理同步原语。让生产者添加商品,消费者消费。该类将为您处理所有同步,并且可能比您的实现更高效。