I have a recursive problem where the consumers do some work at each level of a tree, then need to recurse down the tree and perform that same work at the next level.
I want to use ConcurrentBag
/BlockingCollection
etc to run this in parallel. In this scenario, the consumers of the queue, are also the producers for the queue!
My problem is this : Using BlockingCollection
, I can write very simple foreach
logic to dequeue items, and queue new ones - When the queue is empty, the blocking collection will block correctly, and wait for new work to be produced by one of the other consumers.
But how do I know if all of the consumers are blocking?!
I know about CompleteAdding()
, but that does not seem to serve, as the only time you are actually complete is when all of the producers are done producing and the queue is empty - and since they would all be blocking, there is nobody "free" to set CompleteAdding()
. Is there a way to detect this? (Perhaps an event that can fire when blocking, and fire again when unblocked?)
I can deal with this manually, by not using a foreach
, but manually having a while(!complete)
loop, and using TryTake
, but then I need to manually sleep, which seems inefficent (the whole reason to have the blocking collection vs just the concurrent collections in the first place!) Each time through the loop, if TryTake
is false, I could set an Idle flag, and then have a Master check if the queue is empty, and all threads are idle, set a complete flag, but again, this seems kludgy.
Intuition is telling me there is some way to use BlockingCollection
to do this, but I cant quite get there.
Anyway, anyone have a good pattern for when the consumers are the producers and being able to detect when to release all the blocks would be awesome.
Task
s that each do one iteration only? – Potts