2010-09-29 9 views
21

Ho una coda di blocco limitata in un'applicazione che è stata scritta diversi anni fa. Diciamo solo che l'implementazione è meno che stellare, ma ha funzionato. Tuttavia, ha alcuni problemi di prestazioni. Sembra che .NET 4.0 BlockingCollection<T> sia la sostituzione giusta, ma devo assicurarmi che sia effettivamente una coda. Cioè, è garantito che sia rigorosamente FIFO se usato in un modo single-producer, single-consumer?BlockingCollection <T> garantisce l'ordine di rimozione?

La documentazione non dice esplicitamente. L'argomento BlockingCollection fa dire (nelle osservazioni):

BlockingCollection<T> è simile ad un tradizionali dati della coda blocco struttura, tranne che il meccanismo di memorizzazione dei dati sottostante viene estratta via come IProducerConsumerCollection<T>.

Ma nulla dice espressamente che le cose verranno rimosse nello stesso ordine in cui sono state aggiunte.

Qualcuno sa per certo?

+3

Downgoter, hai qualcosa da dire? È consuetudine dare una ragione per un downvote. –

risposta

38

Bene, BlockingCollection<T> è davvero progettato per il lavoro parallelo, in cui si hanno più "produttori" simultanei e un consumatore (utilizzando GetConsumingEnumerable()).

In questa situazione, non è possibile garantire l'ordine di inserimento, pertanto i vincoli di ordine non sono specificati.

Detto questo, BlockingCollection<T> funziona su qualsiasi IProducerConsumerCollection<T> (specificato nel costruttore). Se non ne fornite uno nella funzione di costruzione, internamente, verrà utilizzato uno ConcurrentQueue<T>. Questo fa sì che sia FIFO, dal momento che sarà effettivamente (internamente) una coda. Quindi sì, per impostazione predefinita, sarà "garantito di essere rigorosamente FIFO se usato in un singolo produttore, moda mono-consumatore", almeno nell'attuale implementazione. Se si vuole forzare questo per il futuro proofing (dal momento che la coda è un dettaglio di implementazione), proprio costruirlo come:

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

che garantiranno che usa una coda adesso e in futuro (dal momento che la coda è un dettaglio di implementazione).

+1

Non sono convinto che l'esistenza di "GetConsumingEnumerable" implichi che la raccolta sia destinata a più produttori e a un singolo consumatore. Certo, quel particolare metodo sembra essere inteso per un singolo consumatore, ma questo certamente non impedisce più consumatori. –

+0

@Jim: Non - ma questa era la motivazione principale dietro a ciò. Più consumatori erano destinati a AddToAny(), in cui ciascuna delle BlockingCollection pertinenti veniva utilizzata da un singolo consumatore.Evento il nome stesso "BlockingCollection" sta suggerendo che "blocchi" (dal lato del consumatore) fino a quando gli articoli non vengono aggiunti. –

+0

Hai risposto alla mia domanda immediata, impedendomi di dover identificarlo personalmente. Grazie. –

1

Forse la documentazione MSDN è stata aggiornata da questa domanda, ma ora indica chiaramente che BlockingCollection verrà impostato su FIFO, se non diversamente indicato.

vedere: https://msdn.microsoft.com/en-us/library/dd997371(v=vs.110).aspx o in caso di MS cambiare il link di Google 'MSDN BlockingCollection Panoramica'

NET Framework 4.6 e 4.5

Cercare 'Specifica del tipo Collection' in quella pagina.

Problemi correlati