2015-12-18 12 views
5

Ho un problema di produttore/consumatore. Attualmente ho un semplice Queue circondato da un lock.ConcurrentQueue che mi consente di attendere su un produttore

Sto provando a sostituirlo con qualcosa di più efficiente.

La mia prima scelta è stata quella di utilizzare un ConcurrentQueue, ma non vedo come far attendere il mio consumatore sul messaggio successivo prodotto (senza fare Thread.Sleep).

Inoltre, vorrei essere in grado di cancellare l'intera coda se le sue dimensioni raggiungono un numero specifico.

Puoi suggerire qualche classe o implementazione esistente che soddisfi i miei requisiti?

+2

Hai provato il [ 'BlockingCollection'] (https://msdn.microsoft.com/en- us/library/dd267312% 28v = vs.110% 29.aspx) classe? –

+0

Dai un'occhiata a [questa domanda] (http://stackoverflow.com/questions/34255759/multiple-producers-single-consumer-locking-schema). Sebbene riguardi più produttori, non importa se hai un singolo produttore. –

+0

Puoi elaborare su _ "per cancellare l'intera coda se le sue dimensioni raggiungono ..." _? Per le altre esigenze, BlockingCollection è la scelta ideale. –

risposta

0

Ecco un esempio di come è possibile utilizzare la classe BlockingCollection di fare ciò che si vuole:

BlockingCollection<int> blocking_collection = new BlockingCollection<int>(); 

//Create producer on a thread-pool thread 
Task.Run(() => 
{ 
    int number = 0; 

    while (true) 
    { 
     blocking_collection.Add(number++); 

     Thread.Sleep(100); //simulating that the producer produces ~10 items every second 
    } 
}); 

int max_size = 10; //Maximum items to have 

int items_to_skip = 0; 

//Consumer 
foreach (var item in blocking_collection.GetConsumingEnumerable()) 
{ 
    if (items_to_skip > 0) 
    { 
     items_to_skip--; //quickly skip items (to meet the clearing requirement) 
     continue; 
    } 

    //process item 
    Console.WriteLine(item); 

    Thread.Sleep(200); //simulating that the consumer can only process ~5 items per second 

    var collection_size = blocking_collection.Count; 

    if (collection_size > max_size) //If we reach maximum size, we flag that we want to skip items 
    { 
     items_to_skip = collection_size; 
    } 
} 
+0

Nice :) Nella mia implementazione iniziale ho fatto un 'while (blocking_collection.TryTake (out obj)) {}' (non è un grosso problema se mi manca ancora un elemento.) Ma ritengo che la tua implementazione sia più veloce e più precisa! Per l'implementazione 'Peek', io uso il' FirstOrDefault() ', cosa ne pensi? So che non sta bloccando qualcos'altro, ma nel mio caso, non importa – J4N

+1

Puoi spiegare perché vuoi sbirciare? Forse c'è un modo migliore per farlo. –

Problemi correlati