2012-06-01 8 views
7

Tengo un problema recursivo en el que los consumidores hacen algo de trabajo en cada nivel de un árbol, luego deben recurrir por el árbol y realizar el mismo trabajo en el siguiente nivel.¿Cómo utilizo una colección de bloqueo en el patrón Productor/Consumidor cuando los productores también son consumidores? ¿Cómo termino?

Quiero usar ConcurrentBag/BlockingCollection, etc. para ejecutar esto en paralelo. En este escenario, los consumidores de la cola también son los productores de la cola.

Mi problema es este: Usando BlockingCollection, puedo escribir una lógica foreach muy simple para dequear elementos, y ponerlos en cola nuevos: cuando la cola está vacía, la colección bloqueante se bloqueará correctamente y esperará a que se produzca un nuevo trabajo uno de los otros consumidores.

Pero, ¿cómo sé si todos los consumidores están bloqueando?

Sé acerca de CompleteAdding(), pero parece que no sirve, ya que la única vez que está completo es cuando todos los productores terminan de producir y la cola está vacía, y como todos estarían bloqueando, no hay nadie "libre" para configurar CompleteAdding(). ¿Hay alguna forma de detectar esto? (Tal vez un evento que puede disparar al bloquear, y disparar nuevamente cuando se desbloquea?)

Puedo manejar esto manualmente, al no usar un foreach, pero tener manualmente un ciclo while (! Complete), y usar TryTake, pero entonces necesito dormir manualmente, lo que parece ineficaz (¡la razón completa para tener la colección de bloqueo frente a las colecciones simultáneas en primer lugar!) Cada vez que pasa el ciclo, si TryTake es falso, podría establecer un indicador de inactividad, y luego tener un control maestro si la cola está vacía, y todos los hilos están inactivos, establecer un indicador completo, pero de nuevo, esto parece kludgy.

La intuición me dice que hay alguna manera de usar Blocking Collection para hacer esto, pero no puedo llegar allí.

De todos modos, alguien tiene un buen patrón para cuando los consumidores son los productores y ser capaz de detectar cuándo liberar todos los bloques sería impresionante

+1

Buena pregunta. Cualquier cosa con banderas externas o eventos parece madura para las condiciones de carrera. –

+0

¿Los procesadores (consumidores/productores combinados) tienen mucho estado o requieren una gran cantidad de recursos? ¿Podría volver a emitir el problema en términos de crear 'Tareas' que cada una haga una iteración solamente? –

+0

@Damien_The_Unbeliever: Sí, puedo hacer una única iteración, y de hecho ya lo tengo funcionando, pero estoy tratando de usar un patrón productor/consumidor ya que este es un código que puede migrarse a la nube en el futuro, donde los roles de los trabajadores serán utilizando el almacenamiento de Azure Queue de la misma manera, y me gustaría mantener la lógica general lo más similar posible entre las dos implementaciones. En ese caso, me veré obligado a comprobar si los trabajadores están ociosos para decidir que la cola está lista, pero parece que debería ser eficiente donde sea posible a nivel local. Además, solo quiero resolver esto :) –

Respuesta

-3

Creo que este enlace de MSDN puede ayudar.

Reusable Parallel Data Structures and Algorithms

Expone cómo tratar con algunas estructuras de datos en escenarios simultáneos.

+1

Las estructuras de datos de 2007 no abordan mi pregunta sobre las 4.0 bibliotecas concurrentes. –

+0

Entonces impleméntelos usted mismo usando 4.0. Es solo una guía, no la "respuesta". – oarrivi

Cuestiones relacionadas