What are the differences between ConcurrentQueue and BlockingCollection in .Net?

.NetGenericsC# 4.0

.Net Problem Overview


What are the differences between ConcurrentQueue and BlockingCollection in .Net?

Why BlockingCollection is best for producer-consumer operation when it can be done through ConcurrentQueue? Do I have to improve anything in the following code?

MessageSlotMachineGameStartOrAndStatusUpdate msg;

while (!aCancellationToken.IsCancellationRequested)
{
    try
    {
        this.isStillConsumingMsg = true;
        Boolean takeResult = this.msgQueue.TryTake(out msg, this.msgConsumeTimeOut, aCancellationToken);
        if (takeResult)
        {
            if (msg != null)
            {
                this.ProcessMessage(msg);
            }
        }
        else
        {
            break;
        }
    }
    catch (OperationCanceledException err)
    {
        EngineManager.AddExceptionLog(err, "Signal Operation Canceled");
    }
    catch (Exception err)
    {
        EngineManager.AddExceptionLog(err, "Signal exception");
    }
    finally
    {
        this.isStillConsumingMsg = false;
    }
}

.Net Solutions


Solution 1 - .Net

BlockingCollection has a Take method that would block the consumer if there is nothing to take, and wait for a producer side to provide an item. ConcurrentQueue lacks such method - if it is empty, the consumer would need to handle the wait, and the producer would need to provide a non-empty notification.

Solution 2 - .Net

The BlockingCollection is a wrapper for concurrent collections, and the default wrapped collection IS a ConcurrentQueue ;-)

From Microsoft BlockingCollection:

> When you create a BlockingCollection object, you can specify not > only the bounded capacity but also the type of collection to use. For > example, you could specify a ConcurrentQueue object for first in, > first out (FIFO) behavior, or a ConcurrentStack object for last in, > first out (LIFO) behavior. You can use any collection class that > implements the IProducerConsumerCollection interface. > The default collection type for BlockingCollection is ConcurrentQueue.

The BlockingCollection has a Take() blocking method (hence the name), but it also has a very interesting GetConsumingEnumerable() method which allows you to loop indefinitely : the code will enter the loop inside code only when something is added to collection. See albahari.com excellent online ebook about Threading.

Here is the code sample from this website:

public class PCQueue : IDisposable
{
  BlockingCollection<Action> _taskQ = new BlockingCollection<Action>(); 
  public PCQueue (int workerCount)
  {
    // Create and start a separate Task for each consumer:
    for (int i = 0; i < workerCount; i++)
      Task.Factory.StartNew (Consume);
  }
 
  public void Dispose() { _taskQ.CompleteAdding(); }
 
  public void EnqueueTask (Action action) { _taskQ.Add (action); }
 
  void Consume()
  {
    // This sequence that we’re enumerating will block when no elements
    // are available and will end when CompleteAdding is called. 
    foreach (Action action in _taskQ.GetConsumingEnumerable())
      action();     // Perform task.
  }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTamilmaranView Question on Stackoverflow
Solution 1 - .NetSergey KalinichenkoView Answer on Stackoverflow
Solution 2 - .NetEloView Answer on Stackoverflow