This article will present some simple code to make use of the ConcurrentQueue collection that lives in the System.Collections.Concurrent namespace in TPL.
The collections available in this namespace are the following:
- ConcurrentBag
- ConcurrentQueue
- ConcurrentStack
- ConcurrentDictionary
- BlockingCollection
This article will focus on the ConcurrentQueue collection. This class is much like a Queue, but it is also thread safe and therefore supports concurrency in a better manner than the ordinary Queue collection.
To enqueue items in the ConcurrentQueue, one uses the Enqueue method. To dequeue items in the ConcurrentQueue, one uses the TryDequeue Method. If this method returns true, the out parameter will contain the object returned from the ConcurrentQueue. Make note also that as the ordinary Queue we add and remove items from the queue in the ordinary First-In First-Out manner (FIFO), obviously because it is called a queue.
The next code shows how to use the ConcurrentQueue:
class Program
{
static void Main(string[] args)
{
ConcurrentQueue<int> queue = new ConcurrentQueue<int>();
foreach (var i in Enumerable.Range(0, 1000))
{
queue.Enqueue(i);
}
Parallel.ForEach(queue, new ParallelOptions {
MaxDegreeOfParallelism = System.Environment.ProcessorCount },
q =>
{
int currentItem;
if (queue.TryDequeue(out currentItem))
Console.WriteLine("Got item: {0}", currentItem);
});
Console.WriteLine("Press any key to continue ...");
Console.ReadKey();
}
In the code above, the code methods Enqueue and TryDequeue is used of the ConcurrentQueue class. Also note the use of the out parameter and the fact that TryDequeue returns a boolean flag that shows if the dequeueing was successful or not. There is a also a method called TryPeek which will inspect the item returned from the front of the queue, but it will not remove the item from the queue.
Often, one will use ConcurrentDictionary also and BlockingCollection is often used to implement Producer-Consumer patterns in a parallel world. ConcurrentStack and ConcurrentBag will also be used in many situations. Of all the concurrent classes, ConcurrentBag looks the simplest to use. The nice part of these classes is that we do not have think too much about locking access to them, since this is already implemented. Actually, do not lock access to these collections at all, one only has to understand each collection and call the correct methods upon them to interact with the collection. Problems around synchronization and parallel access will already be resolved.