1

下面的代码使用后台工作线程一个一个地处理工作项。当工作项用完时,工作线程开始等待 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
4

2 回答 2

3

您使用了错误的同步机制。而不是 MRE,只需使用信号量。然后,信号量将表示尚未处理的项目数。您可以将其设置为加一,或等待它减一。没有if,你总是做每一个信号量动作,因此没有竞争条件。

也就是说,您可以完全避免该问题。与其自己管理同步原语,不如使用BlockingCollection. 让生产者添加项目,让消费者消费它们。同步将由该类为您处理,并且可能比您的实现更有效。

于 2013-09-23T13:58:40.867 回答
0

我倾向于使用当前工作项计数器并增加和减少该计数器。您可以将您的处理器线程变成一个循环,该循环正在查看该计数器然后休眠而不是运行一次并完成。这样,无论您在添加项目时在哪里,您都距正在处理的项目有 1 个睡眠周期。

于 2013-09-23T13:47:32.360 回答