2010-09-29 21 views
21

Tengo una cola de bloqueo delimitada en una aplicación que se escribió hace varios años. Digamos que la implementación es menos que estelar, pero funcionó. Sin embargo, tiene algunos problemas de rendimiento. Parece que el .NET 4.0 BlockingCollection<T> es el reemplazo correcto, pero necesito asegurarme de que realmente se trata de una cola. Es decir, ¿se garantiza que sea estrictamente FIFO si se utiliza de manera individual y de un único consumidor?¿BlockingCollection <T> garantiza la orden de eliminación?

La documentación no dice específicamente. El tema BlockingCollection Qué dice (en las Observaciones):

BlockingCollection<T> es similar a un de datos tradicionales de cola de bloqueo estructura, excepto que el mecanismo de almacenamiento de datos subyacente se abstrae distancia como un IProducerConsumerCollection<T>.

Pero nada dice específicamente que las cosas se eliminarán en el mismo orden en que se agregaron.

¿Alguien sabe con certeza?

+3

Downvoter, usted tiene algo que decir? Es costumbre dar una razón para un downvote. –

Respuesta

38

Bueno, BlockingCollection<T> está realmente diseñado para el trabajo paralelo, donde tiene múltiples "productores" simultáneos y un consumidor (usando GetConsumingEnumerable()).

En esta situación, no tiene forma de garantizar el orden de inserción, por lo que no se especifican las restricciones de ordenación.

Dicho esto, BlockingCollection<T> funciona en cualquier IProducerConsumerCollection<T> (especificado en el constructor). Si no proporciona uno en el constructor, internamente, usará un ConcurrentQueue<T>. Esto hace que sea FIFO, ya que en realidad será (internamente) una cola. Por lo tanto, sí, de manera predeterminada, "se garantiza que será estrictamente FIFO si se utiliza de forma individualizada como un solo consumidor", al menos en la implementación actual. Si desea forzar esto para futuras pruebas (ya que la cola es un detalle de implementación), acaba de construir como:

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

que le garantiza que utiliza una cola ahora y en el futuro (ya que la cola está un detalle de implementación).

+1

No estoy convencido de que la existencia de 'GetConsumingEnumerable' implica que la colección está destinada a múltiples productores y a un solo consumidor. De acuerdo, ese método particular parece estar destinado a un solo consumidor, pero eso ciertamente no previene a los consumidores múltiples. –

+0

@Jim: No es así, pero esa fue la principal motivación detrás de eso. Se pretendía utilizar varios consumidores a través de AddToAny(), donde cada uno de los BlockingCollections relevantes era utilizado por un solo consumidor.Evento el nombre en sí mismo "BlockingCollection" sugiere que "bloquea" (en el lado del consumidor) hasta que se agreguen elementos. –

+0

Respondió mi pregunta inmediata, impidiéndome tener que IDASM yo mismo. Gracias. –

1

Tal vez la documentación de MSDN se haya actualizado desde esta pregunta, pero ahora establece claramente que BlockingCollection se convertirá en FIFO a menos que se indique lo contrario.

ver: https://msdn.microsoft.com/en-us/library/dd997371(v=vs.110).aspx o en caso de MS cambiar el enlace de Google 'MSDN BlockingCollection general'

NET Framework 4.6 y 4.5

Busque 'Especificación de la Colección' en esa página.

Cuestiones relacionadas