C# 何时使用 BlockingCollection 以及何时使用 ConcurrentBag 而不是 List<T>?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15400133/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When to use BlockingCollection and when ConcurrentBag instead of List<T>?
提问by Fulproof
The accepted answer to question "Why does this Parallel.ForEach code freeze the program up?"advises to substitute the List usage by ConcurrentBagin a WPF application.
问题“为什么这个 Parallel.ForEach 代码会冻结程序?”的公认答案。建议在 WPF 应用程序中用ConcurrentBag替换 List 用法。
I'd like to understand whether a BlockingCollectioncan be used in this case instead?
我想了解在这种情况下是否可以使用BlockingCollection代替?
采纳答案by Jon
You can indeed use a BlockingCollection
, but there is absolutely no point in doing so.
您确实可以使用 a BlockingCollection
,但这样做绝对没有意义。
First off, note that BlockingCollection
is a wrapper around a collection that implements IProducerConsumerCollection<T>
. Any type that implements that interface can be used as the underlying storage:
首先,请注意这BlockingCollection
是一个实现IProducerConsumerCollection<T>
. 任何实现该接口的类型都可以用作底层存储:
When you create a
BlockingCollection<T>
object, you can specify not only the bounded capacity but also the type of collection to use. For example, you could specify aConcurrentQueue<T>
object for first in, first out (FIFO) behavior, or aConcurrentStack<T>
object for last in,first out (LIFO) behavior. You can use any collection class that implements theIProducerConsumerCollection<T>
interface. The default collection type forBlockingCollection<T>
isConcurrentQueue<T>
.
创建
BlockingCollection<T>
对象时,您不仅可以指定有界容量,还可以指定要使用的集合类型。例如,您可以ConcurrentQueue<T>
为先进先出 (FIFO) 行为指定一个对象,或ConcurrentStack<T>
为后进先出 (LIFO) 行为指定一个对象。您可以使用任何实现该IProducerConsumerCollection<T>
接口的集合类。的默认集合类型BlockingCollection<T>
是ConcurrentQueue<T>
。
This includes ConcurrentBag<T>
, which means you can have a blocking concurrent bag. So what's the difference between a plain IProducerConsumerCollection<T>
and a blocking collection? The documentation of BlockingCollection
says (emphasis mine):
这包括ConcurrentBag<T>
,这意味着您可以有一个阻塞并发包。那么普通IProducerConsumerCollection<T>
集合和阻塞集合有什么区别呢?的文档BlockingCollection
说(强调我的):
BlockingCollection<T>
is used as a wrapper for anIProducerConsumerCollection<T>
instance, allowing removal attempts from the collection to block until data is available to be removed. Similarly, aBlockingCollection<T>
can be created to enforce an upper-bound on the number of data elements allowedin theIProducerConsumerCollection<T>
[...]
BlockingCollection<T>
用作IProducerConsumerCollection<T>
实例的包装器 ,允许从集合中阻止删除尝试,直到可以删除数据为止。类似地,BlockingCollection<T>
可以创建 a 来强制设置IProducerConsumerCollection<T>
[...] 中允许的数据元素数量的上限。
Since in the linked question there is no need to do either of these things, using BlockingCollection
simply adds a layer of functionality that goes unused.
由于在链接的问题中不需要做这些事情中的任何一件,所以使用BlockingCollection
简单地添加了一层未使用的功能。
回答by Jim Mischel
Yes, you could use BlockingCollection
for that. finishedProxies
would be defined as:
是的,你可以用BlockingCollection
它。finishedProxies
将被定义为:
BlockingCollection<string> finishedProxies = new BlockingCollection<string>();
and to add an item, you would write:
并添加一个项目,你会写:
finishedProxies.Add(checkResult);
And when it's done, you could create a list from the contents.
完成后,您可以根据内容创建一个列表。
回答by Ahmet Arslan
List<T>
is a collection designed to use in single thread applications.ConcurrentBag<T>
is a class ofCollections.Concurrent
namespace designed to simplify using collections in multi-thread environments. If you use ConcurrentCollection you will not have to lock your collection to prevent corruption by other threads. You can insert or take data from your collection with no need to write special locking codes.BlockingCollection<T>
is designed to get rid of the requirement of checking if new data is available in shared collection between threads. if there is new data inserted to shared collection than your consumer thread will awake immediatily. So you do not have to check if new data is available for consumer thread in certain time intervals typically in a while loop.
List<T>
是一个设计用于单线程应用程序的集合。ConcurrentBag<T>
是一类Collections.Concurrent
旨在简化在多线程环境中使用集合的命名空间。如果您使用 ConcurrentCollection,您将不必锁定您的集合以防止其他线程损坏。您可以从您的集合中插入或获取数据,而无需编写特殊的锁定代码。BlockingCollection<T>
旨在摆脱检查线程之间共享集合中是否有新数据可用的要求。如果有新数据插入共享集合,则您的消费者线程将立即唤醒。因此,您不必检查消费者线程在特定时间间隔内(通常在 while 循环中)是否有新数据可用。