2010-09-25 12 views
5

Estoy escribiendo un programa donde un subproceso necesita insertar elementos en la cola, y uno o más subprocesos saca elementos de la cola y los procesa. Para evitar que se quede sin memoria, me gustaría que el subproceso del productor durmiera cuando la cola se llene. Algunos artículos tienen una prioridad más alta que otros, por lo que me gustaría que se procesen primero. Si los artículos tienen la misma prioridad, me gustaría que el que se agregó primero se procese primero.Cola prioritaria observable con buffers protegida contra subprocesos?

Quiero mostrar los 100 mejores elementos más o menos en una cuadrícula de datos WPF, por lo que también debe accederse mediante una hebra de interfaz de usuario. Sería bueno si pudiera notificar al hilo de UI que también ha habido una actualización, es decir, implementa IObservable.

¿Hay una clase de contenedor que hará todo esto?

Para obtener puntos de bonificación, estoy bastante seguro de que no es necesario bloquear la cola completa tanto en enqueing como dequeing.

.NET 4 implementaciones están bien.

+0

BlockingCollection http://msdn.microsoft.com/en-us/library/dd997371.aspx parece prometedor ... pero no menciona nada sobre las prioridades. Sí dice que puede encapsular cualquier cosa que implemente IProducerConsumerCollection ... ¿hay alguna de esas que sea una cola de prioridad? – mpen

+0

Vea este ejemplo http://msdn.microsoft.com/en-us/library/dd460690.aspx –

+1

Las tareas de FWIW se pueden convertir en observables de Rx. ;) –

Respuesta

2

Si está en .NET 4, debe considerar seriamente el Task Parallel Library con un planificador personalizado como el ejemplo QueuedTaskScheduler. No estoy seguro de que cumpla con todos sus requisitos, pero sería un buen comienzo.

+0

-1 ... no resuelve CUALQUIER problema que el usuario haya mencionado. – TomTom

+1

Pude haber estado fuera de lugar con mi respuesta, pero estoy totalmente en desacuerdo con que no podría resolver el problema. El procesamiento de datos en hilos dedicados se está programando efectivamente ordenando los datos en la colección. Una tarea es una abstracción de nivel superior que podría encapsular los datos y su procesamiento sin tratar directamente con los hilos, lo que tiene muchos beneficios. En tal escenario, la programación podría lograrse a través del programador de tareas en su lugar. –

3

No tiene suerte para buscar un contenedor; debe implementar uno usted mismo. Tenga cuidado con las prioridades: la clasificación se vuelve lenta rápidamente. Lo que hago es tener una clase de cola implementada yo mismo que internamente usa múltiples matrices (una por prioridad - codificada baja, media, alta). De esta manera nunca ordeno. Evite bloqueos si puede (se asume multi core) y vaya a Spinlocks (.NET 4.0), son más rápidos/llevan menos sobrecarga en un escenario de cola.

+0

Nunca recurriría a toda la colección en cada inserción ... eso es una locura. Utilizaría varias matrices (o colas) como sugirió, o algún tipo de estructura de árbol. – mpen

+0

Las estructuras de árbol son más lentas que las colas múltiples (pero más eficientes si el número de prioridades posibles es ALTO, lo que raramente tiene sentido). Los reequilibrios de árbol son muy buenos para el precio del infierno, y nunca tendrá que buscar en ellos de todos modos en una cola. – TomTom

2

Lo que he hecho en el pasado es envolver varias colecciones ConcurrentQueue<T> en una - tipo de lo que TomTom suggests. Esto es bastante razonable cuando la cantidad de prioridades que pretendes tener es baja. Por ejemplo, en algunos casos, incluso puede ser suficiente tener dos: alto y bajo. A continuación, el método de TryDequeue sólo se ve algo como esto:

public bool TryDequeue(out T item) 
{ 
    return _highItems.TryDequeue(out item) || _lowItems.TryDequeue(out item); 
} 

Esto no es exactamente una respuesta completa a su pregunta, pero tal vez puede ayudarle a empezar.

+0

No me gusta limitar el número de prioridades posibles. Quiero usar un valor calculado para la prioridad, y no conozco el rango de antemano. – mpen

+0

@Mark: a veces la gente hace esto con algo como 'SortedList >' internamente; pero como TomTom ya lo mencionó, el costo de las prioridades ilimitadas puede terminar por no valer la pena. ¿Qué hay de un compromiso: tener un valor calculado que se traduce a una prioridad predefinida en función de dónde se encuentra dentro de un determinado rango? –

+0

Sí ... Estoy pensando que tal vez eso es lo que debería hacer. Odio poner restricciones arbitrarias a las cosas, pero supongo que estoy creando demasiado trabajo para mí si no lo hago. Estaba a medio camino de implementarlo con el 'SortedDictionary >' cuando me di cuenta de que tendría que bloquear la estructura tanto al enquear como a eliminar para poder administrar las claves, lo que quita parte de la concurrencia beneficio :( – mpen