Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does BlockingCollection<T> guarantee removal order?

Tags:

c#

.net

I have a bounded blocking queue in an application that was written several years ago. Let's just say that the implementation is less than stellar, but it's worked. However, it has some performance problems. It looks like the .NET 4.0 BlockingCollection<T> is the right replacement, but I need to make sure that it is actually a queue. That is, is it guaranteed to be strictly FIFO if used in a single-producer, single-consumer fashion?

The documentation doesn't specifically say. The BlockingCollection topic does say (in the Remarks):

BlockingCollection<T> is similar to a traditional blocking queue data structure, except that the underlying data storage mechanism is abstracted away as an IProducerConsumerCollection<T>.

But nothing specifically says that things will be removed in the same order they're added.

Anybody know for sure?

like image 220
Jim Mischel Avatar asked Sep 29 '10 19:09

Jim Mischel


People also ask

Is BlockingCollection thread-safe?

BlockingCollection<T> is a thread-safe collection class that provides the following features: An implementation of the Producer-Consumer pattern.

What is blocking queue in C#?

If the queue reaches a specific size all threads that are filling the queue will be blocked on add until an item is removed from the queue.


2 Answers

Well, BlockingCollection<T> is really designed for parallel work, where you have multiple simulataneous "producers" and one consumer (using GetConsumingEnumerable()).

In this situation, you have no way to guarantee insertion order, so the ordering constraints aren't specified.

That being said, BlockingCollection<T> works upon any IProducerConsumerCollection<T> (specified in the constructor). If you don't provide one in the constructor, internally, it will use a ConcurrentQueue<T>. This causes it to be FIFO, since it will actually be (internally) a queue. So yes, by default, it will be "guaranteed to be strictly FIFO if used in a single-producer, single-consumer fashion", at least in the current implementation. If you want to force this for future proofing (since the queue is an implementation detail), just construct it as:

var blockingCollection = new BlockingCollection<MyClass>(new ConcurrentQueue<MyClass>()); 

That will guarantee that it uses a queue now, and in the future (since the queue is an implementation detail).

like image 133
Reed Copsey Avatar answered Sep 20 '22 17:09

Reed Copsey


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

see: https://msdn.microsoft.com/en-us/library/dd997371(v=vs.110).aspx or in case MS change the link google 'MSDN BlockingCollection Overview'

NET Framework 4.6 and 4.5

Look for 'Specifying the Collection Type' on that page.

like image 41
pjm Avatar answered Sep 20 '22 17:09

pjm