Search code examples
c#.netmultithreadinglock-free

How do you pause a consumer until objects have been produced in a lock-free manner?


I have two threads, a producer and a consumer.

The producer might not always be producing something. The consumer however, needs to consume it as soon as it becomes available.

The producer thread works in a loop and puts results into a ConcurrentQueue. The consumer thread is in a while (!disposing) loop that calls AutoResetEvent.WaitOne when the system becomes disabled. I've considered calling AutoResetEvent.WaitOne also in the case when the ConcurrentQueue.TryDequeue method returns false; this should only ever happen when there are no items left in the queue.

However, if I were to do this, a deadlock could occur when the following execution is done:

  1. Enqueue
  2. TryDequeue returns true
  3. TryDequeue returns false
  4. Enqueue
  5. WaitOne

This is a possibility in this snippet:

while (this.isDisposing == 0)
{
    if (this.isEnabled == 0)
    {
        this.signal.WaitOne();
    }

    object item;
    if (!this.queue.TryDequeue(out item))
    {
        this.signal.WaitOne();
        continue;
    }

    this.HandleItem(item);
}

What is the proper way to do this without using locks?


Solution

  • I think the BlockingCollection would be good to use here. It will wait efficiently until there is data in the queue. You can combine this with a ConcurrentQueue I think. See http://msdn.microsoft.com/en-us/library/dd267312.aspx