.NET Framework Bucle básico productor-consumidor (BlockingCollection)


Ejemplo

var collection = new BlockingCollection<int>(5);
var random = new Random();

var producerTask = Task.Run(() => {
    for(int item=1; item<=10; item++) 
    {
        collection.Add(item);
        Console.WriteLine("Produced: " + item);
        Thread.Sleep(random.Next(10,1000));
    }
    collection.CompleteAdding();
    Console.WriteLine("Producer completed!");
});

Vale la pena señalar que si no llama a collection.CompleteAdding(); , puede seguir agregando a la colección incluso si su tarea de consumidor se está ejecutando. Simplemente llame a collection.CompleteAdding(); Cuando estés seguro no hay más adiciones. Esta funcionalidad se puede usar para hacer un patrón de Productor múltiple a un Consumidor único en el que tenga múltiples fuentes que alimenten elementos en la Colección de Bloqueo y un consumidor individual extraiga los elementos y haga algo con ellos. Si su BlockingCollection está vacía antes de completar la adición, Enumerable from collection.GetConsumingEnumerable() se bloqueará hasta que se agregue un nuevo elemento a la colección o BlockingCollection.CompleteAdding (); se llama y la cola está vacía.

var consumerTask = Task.Run(() => {
    foreach(var item in collection.GetConsumingEnumerable())
    {
        Console.WriteLine("Consumed: " + item);
        Thread.Sleep(random.Next(10,1000));
    }
    Console.WriteLine("Consumer completed!");
});
  
Task.WaitAll(producerTask, consumerTask);
       
Console.WriteLine("Everything completed!");