The accepted answer to question "Why does this Parallel.ForEach code freeze the program up?" advises to substitute the List usage by ConcurrentBag in a WPF application.
I'd like to understand whether a BlockingCollection can be used in this case instead?
ConcurrentBag is a thread-safe collection class. It allows you to stores items list in unordered way and it also allows you to store duplicate items.
ConcurrentBag<T> is a thread-safe bag implementation, optimized for scenarios where the same thread will be both producing and consuming data stored in the bag.
BlockingCollection<T> is a thread-safe collection class that provides the following features: An implementation of the Producer-Consumer pattern. Concurrent adding and taking of items from multiple threads. Optional maximum capacity. Insertion and removal operations that block when collection is empty or full.
The ConcurrentStack class has a Clear() method which removes all elements from the collection.
You can indeed use a BlockingCollection
, but there is absolutely no point in doing so.
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:
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>
.
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):
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 allowed in theIProducerConsumerCollection<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.
List<T>
is a collection designed to use in single thread applications.
ConcurrentBag<T>
is a class of Collections.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 the shared collection between threads. if there is new data inserted into the shared collection then your consumer thread will awake immediately. So you do not have to check if new data is available for consumer thread in certain time intervals typically in a while loop.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With