2015-12-18 14 views
5

Mam problem Producenta/Konsumenta. Obecnie mam prosty Queue otoczony lock.ConcurrentQueue, która pozwala mi czekać na jednego producenta

Próbuję zastąpić to czymś bardziej wydajnym.

Mój pierwszy wybór polegał na użyciu ConcurrentQueue, ale nie widzę sposobu, aby zmusić konsumenta do czekania na następną wyprodukowaną wiadomość (bez wykonywania Thread.Sleep).

Chciałbym również móc wyczyścić całą kolejkę, jeśli jej rozmiar osiągnie określony numer.

Czy możesz zaproponować istniejącą klasę lub implementację spełniającą moje wymagania?

+2

Czy spróbować [ 'BlockingCollection'] (https://msdn.microsoft.com/en- us/library/dd267312% 28v = vs.110% 29.aspx) klasy? –

+0

Spójrz na [to pytanie] (http://stackoverflow.com/questions/34255759/multiple-producers-single-consumer-locking-schema). Chociaż dotyczy to wielu producentów, nie ma znaczenia, czy masz jednego producenta. –

+0

Czy możesz opracować na _ ", aby wyczyścić całą kolejkę, jeśli jej rozmiar osiągnie ..."? W przypadku innych potrzeb, BlockingCollection jest idealnym wyborem. –

Odpowiedz

0

Oto przykład, w jaki sposób można użyć klasy BlockingCollection robić to, co chcesz:

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 :) W mojej początkowej implementacji zrobiłem 'while (blocking_collection.TryTake (out obj)) {}' (nie jest wielka sprawa, jeśli pominę jeszcze jeden element, ale czuję, że twoja implementacja jest szybsza i bardziej precyzyjna! implementacja 'Peek', używam' FirstOrDefault() ', co o tym myślisz? Wiem, że to nie blokuje czegoś innego, ale w moim przypadku to nie ma znaczenia – J4N

+1

Może wyjaśnić, dlaczego chcesz Może istnieje lepszy sposób na zrobienie tego. –

Powiązane problemy