2010-09-29 12 views
21

Mam ograniczonej kolejki blokowania w aplikacji, która została napisana kilka lat temu. Powiedzmy, że implementacja jest mniej niż gwiezdna, ale zadziałała. Ma jednak pewne problemy z wydajnością. Wygląda na to, że .NET 4.0 BlockingCollection<T> jest właściwym zamiennikiem, ale muszę się upewnić, że faktycznie jest to kolejka. Czy jest to zagwarantowane, że jest to ściśle FIFO, jeśli jest stosowane w jednomandatowym sklepie jednoosobowym?Czy BlockingCollection <T> gwarantuje realizację zlecenia usunięcia?

Dokumentacja nie mówi konkretnie. BlockingCollection temat nie mówi (w uwagach):

BlockingCollection<T> jest podobny do tradycyjne danych kolejki blokowanie struktury, oprócz tego, że pod spodem Dane mechanizm przechowywania jest wydobywane dala jako IProducerConsumerCollection<T>.

Ale nic specjalnie nie mówi, że rzeczy zostaną usunięte w tej samej kolejności, w jakiej zostały dodane.

Ktoś wie na pewno?

+3

Downvoter, masz coś do powiedzenia? Zwyczajowo podajemy powód do odrzucenia. –

Odpowiedz

38

Cóż, BlockingCollection<T> jest naprawdę zaprojektowany do pracy równoległej, w której masz wielu równoczesnych "producentów" i jednego konsumenta (używając GetConsumingEnumerable()).

W tej sytuacji nie można zagwarantować zamówienia reklamowego, więc ograniczenia dotyczące zamawiania nie zostały określone.

Zgodnie z powyższym, BlockingCollection<T> działa na każdym IProducerConsumerCollection<T> (określonym w konstruktorze). Jeśli nie podasz jednego w konstruktorze wewnętrznie, użyje on ConcurrentQueue<T>. Powoduje to, że jest to FIFO, ponieważ będzie on (wewnętrznie) kolejką. Więc tak, domyślnie będzie "gwarantowane ścisłe stosowanie FIFO, jeśli jest używane w trybie jednego producenta, jeden konsument", przynajmniej w obecnej wersji. Jeśli chcesz, aby wymusić to dla przyszłej korekty (ponieważ kolejka jest szczegółów wdrażania), tylko budować ją jako:

var blockingCollection = new BlockingCollection<MyClass>(new ConcurrentQueue<MyClass>()); 

To zagwarantuje, że używa kolejkę teraz, jak iw przyszłości (ponieważ kolejka jest szczegół wdrożenia).

+1

Nie jestem przekonany, że istnienie "GetConsumingEnumerable" oznacza, że ​​kolekcja jest przeznaczona dla wielu producentów i jednego konsumenta. To prawda, że ​​ta konkretna metoda wydaje się być przeznaczona dla pojedynczego konsumenta, ale z pewnością nie zapobiega ona wielu konsumentom. –

+0

@Jim: Nie, ale to była główna motywacja. Wielu konsumentów było przeznaczonych przez AddToAny(), gdzie każdy z odpowiednich BlockingCollections był używany przez jednego konsumenta.Zdarzenie sama nazwa "BlockingCollection" sugeruje, że "blokuje" (po stronie konsumenta), dopóki elementy nie zostaną dodane. –

+0

Odpowiedziałeś na moje bezpośrednie pytanie, uniemożliwiając mi samodzielne IDASM. Dzięki. –

1

Być może dokumentacja MSDN została zaktualizowana od czasu tego pytania, ale teraz wyraźnie stwierdza, że ​​BlockingCollection będzie domyślnie FIFO, chyba że zostanie inaczej wskazane.

patrz: https://msdn.microsoft.com/en-us/library/dd997371(v=vs.110).aspx lub w przypadku MS zmienić google link 'MSDN BlockingCollection Przegląd'

NET Framework 4.6 i 4.5

Poszukaj 'Określanie typu kolekcji' na tej stronie.

Powiązane problemy