Domanda

The below code uses a background worker thread to process work items one by one. The worker thread starts waiting on a ManualResetEvent whenever it runs out of work items. Main thread periodically adds new work items and wakes the worker thread.

The waking mechanism has a race condition. If a new item is added by main thread while worker thread is at the place indicated by *, the worker thread will not get woken.

Is there a simple and correct way of waking the worker thread that does not have this problem?

    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
È stato utile?

Soluzione

You're using the wrong synchronization mechanism. Rather than a MRE just use a Semaphore. The semaphore will then represent the number of items yet to be processed. You can set it to add one, or wait on it to reduce it by one. There is no if, you always do every semaphore action and as a result there is no race condition.

That said, you can avoid the problem entirely. Rather than managing the synchronization primitives yourself you can just use a BlockingCollection. Have the producer add items and the consumer consume them. The synchronization will all be taken care of for you by that class, and likely more efficiently than your implementation would be as well.

Altri suggerimenti

I tend to use a current work items counter and increment and decrement that counter. You can turn your processor thread into a loop that is looking at that counter then sleeping rather than run once and done. That way, no matter where you are when the item is added, you are 1 sleep cycle from the item being processed.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top