BlockingCollection
Learn the producer-consumer pattern with BlockingCollection.
BlockingCollection
BlockingCollection<T> adds blocking behavior on top of a wrapped concurrent collection. Add waits when full; Take waits when empty.
This makes the classic producer-consumer pattern very easy to write. By default it wraps a ConcurrentQueue. You signal no more items with CompleteAdding; the consumer then ends.
Bounded BlockingCollection
new BlockingCollection<int>(5) creates a bounded collection with capacity 5. A sixth Add blocks until space frees; this gives backpressure.
If the producer is fast and the consumer slow, this prevents memory bloat. GetConsumingEnumerable() streams items with blocking until the collection is completed.
Exercise Produce and consume with BlockingCollection
The collection below is empty. Use Add to add three items: "a", "b", "c". Then call CompleteAdding(). Finally print each item with foreach (var item in collection.GetConsumingEnumerable()).
Show example solution
collection.Add("a"); collection.Add("b"); collection.Add("c"); collection.CompleteAdding(); Then foreach (var item in collection.GetConsumingEnumerable()) Console.WriteLine(item);
Example solution:
using System;
using System.Collections.Concurrent;
class Program
{
static void Main()
{
var collection = new BlockingCollection<string>();
collection.Add("a");
collection.Add("b");
collection.Add("c");
collection.CompleteAdding();
foreach (var item in collection.GetConsumingEnumerable())
{
Console.WriteLine(item);
}
}
}
Test yourself
-
Complete the Add call
collection.____;Show answer
collection.Add("job"); -
Match each BlockingCollection method
- Add
- Wait if full, then add
- Take
- Wait if empty, then remove
- CompleteAdding
- Signal no more adds
-
Which collection does BlockingCollection wrap by default?
- ConcurrentStack
- ConcurrentQueue
- ConcurrentBag
- ConcurrentDictionary
Show answer
ConcurrentQueue — Correct. The default wrapped collection is ConcurrentQueue.