I'm playing around with BlockingCollection
to try to understand them better, but I'm struggling to understand why my code hangs when it finishes processing all my items when I use a Parallel.For
I'm just adding a number to it (producer?):
var blockingCollection = new BlockingCollection<long>();
Task.Factory.StartNew(() =>
{
while (count <= 10000)
{
blockingCollection.Add(count);
count++;
}
});
Then I'm trying to process (Consumer?):
Parallel.For(0, 5, x =>
{
foreach (long value in blockingCollection.GetConsumingEnumerable())
{
total[x] += 1;
Console.WriteLine("Worker {0}: {1}", x, value);
}
});
But when it completes processing all the numbers, it just hangs there? What am I doing wrong?
Also, when I set my Parallel.For to 5, does it mean it's processing the data on 5 separate thread?
As its name implies, operations on BlockingCollection<T>
block when they can't do anything, and this includes GetConsumingEnumerable()
.
The reason for this is that the collection can't tell if your producer is already done, or just busy producing the next item.
What you need to do is to notify the collection that you're done adding items to it by calling CompleteAdding()
. For example:
while (count <= 10000)
{
blockingCollection.Add(count);
count++;
}
blockingCollection.CompleteAdding();
It's a GetConsumingEnumerable
method feature.
Enumerating the collection in this way blocks the consumer thread if no items are available or if the collection is empty.
You can read more about it here
Also using Parallel.For(0,5)
doesn't guarantee that the data will be processed in 5 separate threads. It depends on Environment.ProcessorCount
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With