Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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;     } } 
like image 422
Tamilmaran Avatar asked Apr 04 '12 12:04

Tamilmaran


People also ask

What is BlockingCollection?

BlockingCollection<T> is a thread-safe collection class that provides the following features: An implementation of the Producer-Consumer pattern. Concurrent adding and taking of items from multiple threads. Optional maximum capacity. Insertion and removal operations that block when collection is empty or full.

Is ConcurrentQueue thread-safe?

Note that both ConcurrentStack and ConcurrentQueue classes are thread safe and they can manage locking and synchronization issues internally. You can also convert the concurrent queue instance to an array by making a call to the ToArray() method.

Is Blockcollection a FIFO?

Perhaps MSDN documentation has been updated since this question but it now clearly states that BlockingCollection will default to FIFO unless otherwise directed.

Is concurrent queue Blocking?

Unlike a LinkedBlockingQueue, a ConcurrentLinkedQueue is a non-blocking queue. Thus, it does not block a thread once the queue is empty. Instead, it returns null.


2 Answers

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.

like image 79
Sergey Kalinichenko Avatar answered Sep 22 '22 12:09

Sergey Kalinichenko


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.   } } 
like image 24
Elo Avatar answered Sep 20 '22 12:09

Elo