У меня есть рекурсивная проблема, когда потребители выполняют некоторую работу на каждом уровне дерева, затем им нужно рекурсивно пройти вниз по дереву и выполнить ту же работу на следующем уровне.
Я хочу использовать ConcurrentBag/BlockingCollection и т. д. для параллельного запуска. В этом сценарии потребители очереди также являются ее производителями!
Моя проблема заключается в следующем: используя BlockingCollection, я могу написать очень простую логику foreach для удаления элементов из очереди и постановки новых в очередь. Когда очередь пуста, блокирующая коллекция будет правильно блокироваться и ждать, пока новая работа будет выполнена одним других потребителей.
Но как я узнаю, что все потребители блокируются?!
Я знаю о CompleteAdding(), но, похоже, это не работает, так как единственный раз, когда вы фактически завершены, это когда все производители закончили производство и очередь пуста, и поскольку все они будут блокироваться, никто не "свободен" для установки CompleteAdding().Есть ли способ обнаружить это? (Возможно, событие, которое может срабатывать при блокировке и срабатывать снова при разблокировке?)
Я могу справиться с этим вручную, не используя foreach, а вручную используя цикл while(!complete) и используя TryTake, но затем Мне нужно вручную заснуть, что кажется неэффективным (в первую очередь причина в том, чтобы иметь блокирующую коллекцию, а не только параллельные коллекции!) Каждый раз в цикле, если TryTake имеет значение false, я мог бы установить флаг Idle, а затем иметь Мастер проверяет, пуста ли очередь и все потоки бездействуют, устанавливает флаг завершения, но опять же, это кажется неуклюжим.
Интуиция подсказывает мне, что есть какой-то способ использовать Blocking Collection для этого, но я не могу этого понять.
В любом случае, у любого есть хорошая модель, когда потребители являются производителями, и иметь возможность определять, когда освобождать все блоки, было бы здорово