2011-04-30 14 views
12

Necesito una colección concurent que no permita duplicados (para usar en BlockingCollection como Productor/Consumidor). No necesito un orden estricto de elementos. De otra parte quiero minimizar el tiempo máximo de elemento "en vivo" en la colección. Es decir. la colección no debe ser LIFO, idealmente debe ser FIFO.cómo crear no-duplicados ConcurrentQueue?

Bueno, yo diría que necesito ConcurrentQueue sin duplicados permitidos, pero ConcurrentBag sin duplicados también podría funcionar.

¿Por qué C# no contiene nada de eso y probablemente alguien ya lo haya creado?

Esta pregunta es resultado de mi pregunta anterior What type of IProducerConsumerCollection<T> to use for my task?

+5

C# es solo un lenguaje, tendrías que buscar una biblioteca para obtener funcionalidades como esa. Como el .NET framework, el hogar de ConcurrentQueue/Bag. Nadie jamás pensó escribir código así, está condenado al fracaso. Porque no puede predecir exactamente cuándo el productor produce y el consumidor consume. Decidir cuándo eliminar duplicados es más o menos análogo a tomar decisiones basadas en el valor de retorno de Random.Next(). Cualquiera sea la razón por la que tiene que implementar algo así: está condenado al fracaso. –

+0

No entiendo por qué está condenado al fracaso. Puedo simular Set usando ConcurrentDictionary (usaré solo clave, el valor siempre será nulo). No quiero eliminar duplicados. No debe haber duplicados. – javapowered

+0

Además, "C# en Cáscara de Nuez" establece que es posible escribir una pila concurrente: "Si escribía su propia colección simultánea que prohibía duplicados, haría que TryAdd devuelva falso si el elemento ya existía (un ejemplo sería si usted escribió un conjunto concurrente) " – javapowered

Respuesta

1

Bueno, si usted quiere tener estrictamente no hay duplicados, es necesario 'conjuntos'. Por ejemplo, NHibernate usa Iesi.Collections para proporcionar dicha funcionalidad. Tomando Iesi, puede construir su propia funcionalidad en torno a las clases proporcionadas 'Set' (DictionarySet, HashSet, SortedSet). Fuente: http://www.codeproject.com/KB/recipes/sets.aspx

+1

.Net tiene un' HashSet '. Por lo que he encontrado, NHibernate usa 'Iesi.Collections' para' ISet '(que no tiene una buena alternativa en las bibliotecas .Net). – svick

+0

Sí, nuevo con .net 3.5 y superior. –

3

No hay bibliotecas .Net integradas que combinen este conjunto de reglas para una colección. Tiene tres opciones:

  1. Escriba su propia clase de colección
  2. Uso dos colecciones: Escribir una clase personalizada que utiliza uno ConcurrentQueue y cualquier colección basada en el Conjunto que se auto-comprobaciones de duplicados; agregar a Ejecutar ejecución y si tiene éxito, agregar a ConcurrentQueue; cada añadir/quitar sumaría a las dos colecciones exitosas cuando
  3. Uso ConcurrentQueue pero iterar a través de toda la lista de comprobación de un duplicado

Los dos últimos no son muy eficientes (uno con la memoria, el otro con la CPU, E/S, bloqueo) y son más complicados debido a la necesidad de bloqueo explícito, pero cumplirían la tarea. Serán más rápidos de implementar, pero si las compensaciones no cumplen con sus requisitos, tendrá que ir con la opción n. ° 1.

-3

Puede simplemente usar un ConcurrentQueue y antes de llamar al Enqueue compruebe si los datos están en la cola llamando al método ConcurrentQueue.Contains<>. Supongo que el método de extensión Contains<> está bastante bien optimizado.

EDIT: Como otros han señalado, para que esto funcione sería que tendría que utilizar un mecanismo de bloqueo tales como etc exclusión mutua en torno al método Contains<> y el método Enqueue así:

get mutex 
if not Contains<> 
{ 
    Enqueue 
} 
release mutex 
+3

Creo que eso no funcionaría porque una condición de carrera podría permitir que otro hilo Enqueue un objeto "igual" entre la llamada a Contiene y En cola. Realmente necesitaríamos un ConcurrentSet <> para hacer esto bien. – ALEXintlsos

+0

A continuación, agregue un mutex alrededor del código crítico ... – Chimera

+2

... en cuyo caso no necesitaría una versión simultánea del objeto de la cola. Creo que el póster original buscaba un ConcurrentSet que evitara automáticamente los duplicados. – ALEXintlsos