.NET Framework Ciclo base produttore-consumatore (BlockingCollection)


Esempio

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 notare che se non si chiama collection.CompleteAdding(); , puoi continuare ad aggiungere alla raccolta anche se l'attività dell'utente è in esecuzione. Basta chiamare collection.CompleteAdding(); quando sei sicuro che non ci siano più aggiunte. Questa funzionalità può essere utilizzata per creare un produttore multiplo su un modello consumer singolo in cui sono presenti più origini che alimentano elementi in BlockingCollection e un singolo utente che estrae elementi e ne fa qualcosa. Se BlockingCollection è vuoto prima di chiamare l'aggiunta completa, l'Enumerable from collection.GetConsumingEnumerable() bloccherà fino a quando un nuovo elemento non verrà aggiunto alla raccolta o BlockingCollection.CompleteAdding (); viene chiamato e la coda è vuota.

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!");