ConcurrentBag
This is a collection of values. Threads must often access a single collection of values. Sometimes look up functionality is not required.
ConcurrentBag
allows us to safely Add and Take
results. We can use it on a single thread, but it is most useful on multiple threads.
Here we use ConcurrentBag
on a single thread. The bag should be used only when multiple threads access it. In the code we show how Add, TryPeek
and TryTake
work.
Add()
method adds an element to the inside of the ConcurrentBag
—the argument type matches the bag's type parameter.TryPeek
returns, in its out parameter, the value most recently added to the bag. It does not change the bag's contents.TryTake
returns, in the out parameter, the most recently added element. It removes the element from the contents.using System; using System.Collections.Concurrent; class Program { static void Main() { ConcurrentBag<int> bag = new ConcurrentBag<int>(); bag.Add(1); bag.Add(2); bag.Add(3); int result; if (bag.TryPeek(out result)) { Console.WriteLine("TryPeek: {0}", result); } if (bag.TryTake(out result)) { Console.WriteLine("TryTake: {0}", result); } if (bag.TryPeek(out result)) { Console.WriteLine("TryPeek: {0}", result); } } }TryPeek: 3 TryTake: 3 TryPeek: 2
It is possible to create a ConcurrentBag
from its constructor. No calls to Add()
are needed. Many programs, when starting, have known values to use.
string
type. And its constructor can be passed a string
array. The bag has 3 elements.using System; using System.Collections.Concurrent; class Program { static void Main() { // ... Create bag from string array. string[] array = { "Dot", "Net", "Perls" }; ConcurrentBag<string> bag = new ConcurrentBag<string>(array); string value; if (bag.TryPeek(out value)) { Console.WriteLine("TryPeek: {0}", value); } Console.WriteLine("Count: {0}", bag.Count); } }TryPeek: Perls Count: 3
The internals of ConcurrentBag
are surprisingly complex. This class
maintains its internal elements in a private ThreadLocalList
.
ConcurrentBag
, when it cannot TryTake
something, will attempt to TrySteal
it instead. ConcurrentBag
always gets what it wants.The ConcurrentBag
uses the Interlocked
class
to provide thread-safety, as in the TryTakeOrPeak
method. This helps simplify handling fields.
A ConcurrentBag
is simple. This is its main advantage over other collections such as ConcurrentDictionary
. For threading, a complex task itself, simplicity is important.