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

Когда использовать BlockingCollection и когда ConcurrentBag вместо List <T>?

принятый ответ на вопрос "Почему этот код Parallel.ForEach блокирует программу?" рекомендует заменить использование списка ConcurrentBag в приложении WPF.

Я хотел бы понять, можно ли вместо этого использовать BlockingCollection?

4b9b3361

Ответ 1

Вы действительно можете использовать BlockingCollection, но нет абсолютно никакого смысла в этом.

Прежде всего, обратите внимание, что BlockingCollection является оберткой вокруг коллекции, которая реализует IProducerConsumerCollection<T>. Любой тип, реализующий этот интерфейс, может использоваться в качестве основного хранилища:

Когда вы создаете объект BlockingCollection<T>, вы можете указать не только ограниченная емкость, но также и тип используемой коллекции. Для Например, вы можете указать объект ConcurrentQueue<T> для первого входа, (FIFO) или объект ConcurrentStack<T> для последнего in, first out (LIFO). Вы можете использовать любой класс коллекции, который реализует интерфейс IProducerConsumerCollection<T>. По умолчанию тип коллекции для BlockingCollection<T> - ConcurrentQueue<T>.

Это включает ConcurrentBag<T>, что означает, что вы можете иметь блокирующий параллельный пакет. Итак, какая разница между простой IProducerConsumerCollection<T> и блокирующей коллекцией? В документации BlockingCollection говорится (внимание мое):

BlockingCollection<T> используется как обертка для IProducerConsumerCollection<T> экземпляр , позволяющий удалять попытки от коллекции до блока, пока данные не будут удалены. Аналогично, a BlockingCollection<T> может быть создан для принудительно верхняя граница количества допустимых элементов данных в IProducerConsumerCollection<T> [...]

Так как в связанном вопросе нет необходимости делать любую из этих вещей, использование BlockingCollection просто добавляет слой функциональности, который не используется.

Ответ 2

  • List<T> - это коллекция, предназначенная для использования в одном потоке приложения.

  • ConcurrentBag<T> является подтипом ConcurrentCollection<T>, разработанным для упрощения использования коллекций в многопоточных средах. если ты используйте ConcurrentCollection, вам не придется блокировать для предотвращения коррупции другими потоками. Вы можете вставить или брать данные из вашей коллекции, не требуя писать специальные коды блокировки.

  • BlockingCollection<T> призван избавиться от требования проверка наличия новых данных в общей коллекции между потоки. если в общую коллекцию добавлены новые данные, кроме потребительская нить пробудет незамедлительно. Поэтому вам не нужно проверять если новые данные доступны для потребительского потока в определенное время интервалы обычно в цикле while.

Ответ 3

Да, вы можете использовать BlockingCollection для этого. finishedProxies будет определяться как:

BlockingCollection<string> finishedProxies = new BlockingCollection<string>();

и добавить элемент, вы должны написать:

finishedProxies.Add(checkResult);

И когда это будет сделано, вы можете создать список из содержимого.