Как использовать блокирующий набор в шаблоне «Производитель/Потребитель», когда производители также являются потребителями. Как закончить?

У меня есть рекурсивная проблема, когда потребители выполняют некоторую работу на каждом уровне дерева, затем им нужно рекурсивно пройти вниз по дереву и выполнить ту же работу на следующем уровне.

Я хочу использовать ConcurrentBag/BlockingCollection и т. д. для параллельного запуска. В этом сценарии потребители очереди также являются ее производителями!

Моя проблема заключается в следующем: используя BlockingCollection, я могу написать очень простую логику foreach для удаления элементов из очереди и постановки новых в очередь. Когда очередь пуста, блокирующая коллекция будет правильно блокироваться и ждать, пока новая работа будет выполнена одним других потребителей.

Но как я узнаю, что все потребители блокируются?!

Я знаю о CompleteAdding(), но, похоже, это не работает, так как единственный раз, когда вы фактически завершены, это когда все производители закончили производство и очередь пуста, и поскольку все они будут блокироваться, никто не "свободен" для установки CompleteAdding().Есть ли способ обнаружить это? (Возможно, событие, которое может срабатывать при блокировке и срабатывать снова при разблокировке?)

Я могу справиться с этим вручную, не используя foreach, а вручную используя цикл while(!complete) и используя TryTake, но затем Мне нужно вручную заснуть, что кажется неэффективным (в первую очередь причина в том, чтобы иметь блокирующую коллекцию, а не только параллельные коллекции!) Каждый раз в цикле, если TryTake имеет значение false, я мог бы установить флаг Idle, а затем иметь Мастер проверяет, пуста ли очередь и все потоки бездействуют, устанавливает флаг завершения, но опять же, это кажется неуклюжим.

Интуиция подсказывает мне, что есть какой-то способ использовать Blocking Collection для этого, но я не могу этого понять.

В любом случае, у любого есть хорошая модель, когда потребители являются производителями, и иметь возможность определять, когда освобождать все блоки, было бы здорово

7
задан Jason Coyne 1 June 2012 в 14:22
поделиться