In C#, traditional collection classes are using with a lock, but concurrent collection classes are lock free. So, it will often use in parallel programming for performance concern. ConcurrentDictionary runs three times faster than Dictionary.
The concurrent collections can sometimes be useful in general multithreading when we need a thread-safe collection. However, there are some conditions:
- The concurrent collections are using in highly concurrent scenarios.
- A thread-safe collection doesn’t guarantee that the code using it will be thread-safe.
- If we enumerate over a concurrent collection while another thread is modifying
- it, no exception is thrown.
- There’s no concurrent version of List<T> in concurrent collections.
- The concurrent stack, queue, and bag classes are implemented internally with
- linked lists.
In Framework 4.0 provides a set of new collections in the
System.Collections.Concurrent namespace. All of these are fully thread-safe:
In the IProducerConsumerCollection<T> interface defines methods to manipulate
thread-safe collections intended for producer/consumer usage. A
producer/consumer collections which is the two primary use cases. These are:
- Adding an element (“producing”)
- Retrieving an element (“consuming”)
The IProducerConsumerCollection<T> interface are implementing three classes
these are follows:
This interface also extends ICollection interface for adding the following methods:
bool TryAdd (T item);
bool TryTake (out T item);
The TryAdd and TryTake methods test add and remove operation for eliminating
the need of lock. If the collection is empty TryTake returns false otherwise, TryAdd
always succeeds and returns true.
ConcurrentBag<T> stores an unordered collection of objects (it allows duplicates contents). ConcurrentBag<T> is prefer in situations when we do not care which element we get when calling TryTake or Take.
The benefit of ConcurrentBag<T> over a concurrent queue or stack is that a bag’s Add method suffers almost no contention when called by many threads at once. A concurrent bag would be a poor choice for a producer/consumer queue, because elements are added and removed by different threads.
If we call TryTake on any of the producer/consumer collections we discussed previously and the collection is empty, the method returns false. Sometimes it would be more useful in this scenario to wait until an element is available. Rather than overloading the TryTake methods
Here we use BlockingCollection<T> (exception handling aside) in a program:
public static void BC_AddTakeCompleteAdding()
using (BlockingCollection<string> bc = new BlockingCollection<string>())
// Spin up a Task to populate the BlockingCollection
using (Task t1 = Task.Factory.StartNew(() =>
for (int i = 1; i <=10; i++)
bc.Add("HI Guest "+i);
// Spin up a Task to consume the BlockingCollection
using (Task t2 = Task.Factory.StartNew(() =>
// Consume consume the BlockingCollection
while (true) Console.WriteLine(bc.Take());
// An InvalidOperationException means that Take() was called on a completed
Console.WriteLine("That's All. Everything is Ok!");
static void Main()
Console.WriteLine(@" Let's try to use Concurrent collection");
Because we didn’t pass anything into Blocking Collection’s constructor, it instantiated a concurrent queue automatically.
For details we see also: