BlockingCollection<T> coordinates thread-safe producers and consumers by waiting when no item is available. It fits work queues where background workers process items sequentially or concurrently. section 8.2.2 section 13.2.2
Use the collection through a small set of operations:
- Add enqueues an item for processing. section 8.2.2
- GetConsumingEnumerable supports foreach and waits while the queue is empty. section 8.2.2
- CompleteAdding signals that no more items will arrive, allowing consumers to finish after draining the queue. section 8.2.2
- Bounded capacity prevents producers from getting too far ahead of consumers. section 13.2.2
The default backing collection is ConcurrentQueue<T>, preserving first-in, first-out order. ConcurrentStack<T> provides last-in, first-out behavior, while ConcurrentBag<T> is specialized for threads that both read and write items. section 13.2.2
Background mail processing
A mail-merging component enqueues personalized messages, starts a processing thread, consumes them with GetConsumingEnumerable, logs send failures, and stops by calling CompleteAdding. Multiple workers can consume the same queue when processing parallelism is useful. section 8.2.2 section 13.2.2
Listing 13.11 BlockingCollection with 10 processing threads
BlockingCollection<int> blockingCollection = new BlockingCollection<int>();
Thread[] workers = new Thread[10];
for(int i=0; i<workers.Length; i++) #1
{
workers[i] = new Thread(threadNumber =>
{
var rng = new Random((int)threadNumber);
int count = 0;
foreach (var currentValue in
blockingCollection.GetConsumingEnumerable())
{
Console.WriteLine($"thread {threadNumber} value {currentValue}");
Thread.Sleep(rng.Next(500));
count++;
}
Console.WriteLine($"thread {threadNumber}, total {count} items");
});
workers[i].Start(i);
}
for(int i=0;i<100;i++) #2
{
blockingCollection.Add(i);
}
blockingCollection.CompleteAdding(); #3
foreach (var curentThread in workers) #4
curentThread.Join();
A complete pattern starts ten worker threads, consumes values with GetConsumingEnumerable, adds one hundred items, calls CompleteAdding, and waits for workers to finish. section 13.2.2
