Si tiene .Net 4.0 o más alto que puede hacerlo de esta manera mediante el uso de un BlockingCollection
int maxBufferCap = 500;
BlockingCollection<MagicalObject> Collection
= new BlockingCollection<MagicalObject>(maxBufferCap);
void Producer()
{
while (magic.HasMoreMagic)
{
this.Collection.Add(magic.ProduceMagic());
}
this.Collection.CompleteAdding();
}
void Consumer()
{
foreach (MagicalObject magicalObject in this.Collection.GetConsumingEnumerable())
{
DoSomthing(magicalObject);
}
}
La línea foreach
va a dormir si no hay datos en la memoria intermedia, también se activará automáticamente cuando se agregue algo a la colección.
El motivo por el que establezco el búfer máximo es que si su productor es mucho más rápido que el consumidor, puede terminar consumiendo mucha memoria a medida que más objetos entran en la colección. Al configurar un tamaño de búfer máximo a medida que crea la colección de bloqueo cuando se alcanza el tamaño de búfer, la llamada Add
en el productor se bloqueará hasta que el consumidor elimine un elemento de la colección.
Otra ventaja de la clase BlockingCollection
es que puede tener tantos productores y consumidores como desee, no necesita ser una relación 1: 1. Si DoSomthing
admite que usted podría tener un bucle foreach
por núcleo del ordenador (o incluso el uso Parallel.ForEach
y utilizar el enumerables consume como fuente de datos)
void ConsumersInParalell()
{
//This assumes the method signature of DoSomthing is one of the following:
// Action<MagicalObject>
// Action<MagicalObject, ParallelLoopState>
// Action<MagicalObject, ParallelLoopState, long>
Paralell.ForEach(this.Collection.GetConsumingEnumerable(), DoSomthing);
}
Qué versión de .Net estás usando, hay algunas cosas nuevas en v4 para exactamente esto –
.Net 3.5; Los comentarios deben tener al menos 15 caracteres de longitud. –