Подтвердить что ты не робот

Как создать дубликаты ConcurrentQueue?

Мне нужна коллективная коллекция, которая не позволяет дублировать (использовать в BlockingCollection как Producer/Consumer). Мне не нужен строгий порядок элементов. С другой стороны, я хочу свести к минимуму максимальное время элемента "живой" в коллекции. То есть коллекция не должна быть LIFO, в идеале она должна быть FIFO.

Ну, я бы сказал, что мне нужно ConcurrentQueue без дубликатов, но ConcurrentBag без дубликатов также может работать.

Почему С# не содержит ничего подобного и, возможно, кто-то уже создал его?

Этот вопрос является результатом моего предыдущего вопроса Какой тип IProducerConsumerCollection <T> использовать для моей задачи?

4b9b3361

Ответ 1

Нет встроенных библиотек .Net, которые объединяют этот набор правил для коллекции. У вас есть три варианта:

  • Напишите свой собственный класс коллекции
  • Используйте две коллекции: Напишите пользовательский класс, который использует один ConcurrentQueue и любую сборку на основе Set, которая автоматически проверяет дубликаты; добавьте в Set run и в случае успеха добавьте ConcurrentQueue; каждый add/remove добавит в обе коллекции при успешном завершении
  • Используйте ConcurrentQueue, но повторяйте весь список, проверяя дубликат

Последние два не очень эффективны (один с памятью, другой с процессором, ввод-вывод, блокировка) и беспорядочны из-за необходимости явной блокировки, но выполнили бы эту задачу. Они будут быстрее реализованы, но если компромиссы не соответствуют вашим требованиям, вам придется перейти с опцией № 1.

Ответ 2

Хорошо, если вы строго не хотите дублировать, вам нужны "Наборы". Например, NHibernate использует Iesi.Collections для обеспечения такой функциональности. Принимая Iesi, вы можете создать свою собственную функциональность вокруг предоставленных классов "Set" (DictionarySet, HashSet, SortedSet). Источник: http://www.codeproject.com/KB/recipes/sets.aspx

Ответ 3

Вы можете просто использовать ConcurrentQueue и перед вызовом Enqueue проверить, находятся ли данные в очереди, вызвав метод ConcurrentQueue.Contains<>. Я предполагаю, что метод расширения Contains<> довольно хорошо оптимизирован.

EDIT: Как отмечали другие, для этого вам нужно было бы использовать механизм блокировки, такой как мьютекс и т.д. Вокруг метода Contains<> и метода Enqueue, как это:

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