2011-04-01 7 views
5

Tengo una aplicación C# 4.0 con "alta prioridad" y las colas de "baja prioridad" implementado como tal:algoritmo para el procesamiento de .NET hilo consumidor de dos colas (basado en prioridad)

BlockingCollection highPriority = new BlockingCollection (1000); BlockingCollection lowPriority = new BlockingCollection (1000);

Cualquier dato producido en highPriority debe consumirse antes que cualquier dato producido en lowPriority. El giro aquí es que los datos pueden producirse en cualquiera de las dos colas en cualquier momento. Entonces, después de haber consumido todos los datos en highPriority, entonces voy a consumir cualquier información que pueda estar en lowPriority. Si se producen nuevos datos en highPriority mientras estoy consumiendo datos en lowPriority, quiero terminar de consumir el elemento actual en lowPriority y luego volver a procesar los datos en highPriority.

¿Alguien puede sugerir un algoritmo para ayudar con esto? El seudo código está bien. Muchas gracias.

Respuesta

1

Usted querrá terminar con esto en un solo objeto, si puede, como se sugiere @ Kevin Brock, y tienen ese objeto implementar IProducerConsumerCollection. De lo contrario, su código que llame al TryDequeue tendrá que hacer un ciclo de espera ocupado. Es decir, con dos colas, usted tiene que escribir algo como:

WorkItem item = null; 
do 
{ 
    if (!hpQueue.TryDequeue(out item)) 
    { 
     lpQueue.TryDequeue(out item); 
    } 
while (item != null); 

Si utiliza su propia clase, a continuación, puede utilizar los eventos (EventWaitHandle, etc.) para evitar la espera ocupada.

En verdad, probablemente sería mejor utilizar una cola de prioridad. Sería bastante fácil hacer que una cola de prioridad sea segura para subprocesos e implementar IProducerConsumerCollection, y luego puede usarla con BlockingCollection. Un buen lugar para comenzar sería Julian Bucknall's Priority Queue in C#.

+0

¡Muchas gracias! – user685869

3

¿Qué tal esto:

while(true) 
{ 
    workitem = highQueue.dequeue(); 

    if(workitem == null) 
     workitem = lowQueueu.dequeue() 

    process(workitem) 
} 
+0

Me gustaría abstraer esto si necesita proporcionar esto a otras clases de clientes - simplemente haga su propia clase 'IProducerConsumerCollection' que contiene ambos de estos (alta y baja prioridad) y luego proporcionar a las clases del cliente una instancia de 'BlockingCollection' respaldado por ese especial' IProducerConsunmerCollection'. Su clase personalizada puede proporcionar el objeto disponible que la solución de Carra internamente. –

+0

Una idea interesante, pero su código omite algunos problemas fundamentales, como lo que sucede cuando ambas colas están vacías. Además, su ciclo es básicamente una espera ocupada que comprueba continuamente los elementos en lugar de usar un manipulador de espera de algún tipo. No recomendaría esta solución. –

+0

Se simplifica. Normalmente agregaría un proceso if (workitem! = Null) (workitem) else Thread.Sleep (100) o algo similar. – Carra

1

Haría esto con una única cola de prioridad. Esto le permitiría agregar una tercera prioridad más adelante, con muy poco cambio de código.

He escrito uno antes de usar un lockFree-SkipList, pero aquí hay un proyecto para uno que usa una lista de omisiones normal (http://www.codeproject.com/KB/recipes/PriorityQueueSkipList.aspx). Utilicé una lista de omisiones porque se desarrollan bien bajo concurrencia y son bastante simples de implementar (menos la versión sin bloqueo).

También he visto una cola de prioridad en CodePlex que usa un árbol rojo-negro, pero no puedo encontrarlo ahora. ACTUALIZACIÓN: La implementación de cola de prioridad en la que estaba pensando era parte del proyecto NGenerics: http://code.google.com/p/ngenerics/

+0

¡Muchas gracias por su sugerencia!¡No elegí esta como la respuesta, pero aprecio tu aporte! – user685869

+0

¡Codifica bien! y Buena suerte en su proyecto :-) – eSniff

Cuestiones relacionadas