I am using a .NET 4.0 BlockingCollection to handle a queue of items that each need to be processed by an operation that can take up to a second to process each item. This queue
GetConsumingEnumerable
is in fact safe to call from multiple consumers simultaneously; the enumerable only completes when the collection is marked as complete. Each item is only consumed once.
GetConsumingEnumerable
is essentially equivalent to:
while (!IsCompleted)
{
if (TryTake(out var item, Timeout.Infinite))
yield return item;
}
plus a bit of cancellation/cleanup logic.
Multiple consumers can just call Take
or TryTake
concurrently - each item will only be consumed by a single consumer.
However, I believe GetConsumingEnumerable
will also do what you want. I believe if each caller calls that, each will get a separate consuming enumerable, which again will make sure that each item is only consumed once. I'm not sure offhand what happens when the queue becomes empty - I don't know whether MoveNext()
then blocks, or returns false.
I didn't really follow your second question though...