Using a thread-safe dictionary in .NET C# Part 3: thread-safe modifications

In the previous post we looked at the 4 Try methods of ConcurrentDictionary that support CRUD operations: retrieval, deletion, update and insertion. We saw some basic examples for their usage and concluded that TryUpdate was not a very good solution to actually update an item due to race conditions.

This is where another method called AddOrUpdate enters the scene.

As the method name implies it can both update an existing value or add a new key-value pair if the key doesn’t exist yet. There are similar operations in the database world. It’s a mixture of UPDATE and INSERT called an UPSERT. AddOrUpdate is the ConcurrentDictionary equivalent of an UPSERT.

AddOrUpdate requires 3 parameters:

  • The key
  • The value if there’s no element by that key. In this case a new key-value pair will be added to the dictionary
  • A function which will calculate the new value if an element by that key already exists. This is the update part of the operation

The update function – or delegate – in turn has the following requirements:

  • Its signature must accept a key and a value whose types correspond to the key and value type of the ConcurrentDictionary
  • It must return a value of the same type that the ConcurrentDictionary requires

If you’re new to delegates, functions and lambdas then they may look very cryptic at first. You can start your investigation here.

The update function provides a mechanism to calculate the new value based on the key and the existing value. It can be as simple or complex as you need. It always returns the value that was either added in case of a new item or the updated value if it’s an update.

Here’s an example of the AddOrUpdate method:

public void RunAddOrUpdateSample()
{
	ConcurrentDictionary<string, int> movieCategoriesOnStock = new ConcurrentDictionary<string, int>();
	movieCategoriesOnStock.TryAdd("Romance", 12);
	movieCategoriesOnStock.TryAdd("Action", 9);
	movieCategoriesOnStock.TryAdd("Comedy", 20);
	Debug.WriteLine("Dictionary content before AddOrUpdate:");
	foreach (var kvp in movieCategoriesOnStock)
	{
		Debug.WriteLine(string.Format("{0}: {1}", kvp.Key, kvp.Value));
	}

	int zombie = movieCategoriesOnStock.AddOrUpdate("Zombie", 10, (key, value) => { return value * 2; });
	Debug.WriteLine("Zombie: {0}", zombie);

	int romance = movieCategoriesOnStock.AddOrUpdate("Romance", 5, (key, value) => { return CalculateNewValue(key, value); });
	Debug.WriteLine("Romance: {0}", romance);

	Debug.WriteLine("Dictionary content after AddOrUpdate:");
	foreach (var kvp in movieCategoriesOnStock)
	{
		Debug.WriteLine(string.Format("{0}: {1}", kvp.Key, kvp.Value));
	}
}

private int CalculateNewValue(string key, int value)
{
	return key.GetHashCode() + value * 3;
}

This produces the following output:

Dictionary content before AddOrUpdate:
Action: 9
Romance: 12
Comedy: 20
Zombie: 10
Romance: -1978843422
Dictionary content after AddOrUpdate:
Action: 9
Romance: -1978843422
Zombie: 10
Comedy: 20

Romance got a crazy value but I just wanted to take an example where both the key and the value input parameters are used. Again, if the lambda functions look weird then you can consult the course referenced above.

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

Advertisements

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

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 )

Google+ photo

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

Connecting to %s

ultimatemindsettoday

A great WordPress.com site

Elliot Balynn's Blog

A directory of wonderful thoughts

Robin Sedlaczek's Blog

Developer on Microsoft Technologies

HarsH ReaLiTy

A Good Blog is Hard to Find

Softwarearchitektur in der Praxis

Wissenswertes zu Webentwicklung, Domain-Driven Design und Microservices

the software architecture

thoughts, ideas, diagrams,enterprise code, design pattern , solution designs

Technology Talks

on Microsoft technologies, Web, Android and others

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

Anything around ASP.NET MVC,WEB API, WCF, Entity Framework & AngularJS

Cyber Matters

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

Guru N Guns's

OneSolution To dOTnET.

Johnny Zraiby

Measuring programming progress by lines of code is like measuring aircraft building progress by weight.

%d bloggers like this: