Thread-safe bags in .NET

Bags are very similar to Stacks and Queues. We saw that both stacks and queues order their elements in a well defined way: last-in-first-out and first-in-first-out respectively. Bags on the other hand are unordered collections. There’s no guarantee on how, i.e. in which order the elements will be retrieved.

Unlike stacks and queues, bags have no one-to-one single-threaded implementation in .NET. They are however implemented as thread-safe ConcurrentBag objects in the System.Collections.Concurrent namespace.

Here’s some terminology:

  • You can insert new items to a concurrent bag with the Add method, like in the case of a List
  • A single item is removed using the TryTake method. It returns false in case there was nothing to retrieve from the bag. If it returns true then the retrieved item is returned as an “out” parameter
  • You can check the next item using the TryPeek method. It works the same way as TryTake but it doesn’t remove the element from the collection

The following example shows the ConcurrentBag in action. The code fills up a bag of integers with 1000 elements and starts 4 different threads that all read from the shared bag. There’s a very similar code example in the post on ConcurrentQueue and if you run both samples then you’ll see that ConcurrentBags and ConcurrentQueues behave very similarly in practice:

public class ConcurrentBagSampleService
{
	private ConcurrentBag<int> _integerBag = new ConcurrentBag<int>();

	public void RunConcurrentBagSample()
	{
		FillUpBag(1000);
		Task readerOne = Task.Run(() => GetFromBag());
		Task readerTwo = Task.Run(() => GetFromBag());
		Task readerThree = Task.Run(() => GetFromBag());
		Task readerFour = Task.Run(() => GetFromBag());
		Task.WaitAll(readerOne, readerTwo, readerThree, readerFour);
	}

	private void FillUpBag(int max)
	{
		for (int i = 0; i <= max; i++)
		{
			_integerBag.Add(i);
		}
	}

	private void GetFromBag()
	{
		int res;
		bool success = _integerBag.TryTake(out res);
		while (success)
		{
			Debug.WriteLine(res);
			success = _integerBag.TryTake(out res);
		}			
	}
}

Each thread will try to take items from the shared bag as long as TryTake returns false. In that case we know that there’s nothing more left in the collection.

View the list of posts on the Task Parallel Library here.

Advertisement

About Andras Nemes
I'm a .NET/Java developer living and working in Stockholm, Sweden.

One Response to Thread-safe bags in .NET

  1. Pingback: Summary of thread-safe collections in .NET – .NET training with Jead

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Elliot Balynn's Blog

A directory of wonderful thoughts

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Once Upon a Camayoc

Bite-size insight on Cyber Security for the not too technical.

%d bloggers like this: