Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add item to dictionary "Parallel loop safe"

I have a Parallel.ForEach loop doing some treatment. But the first operation is to add a value in the dictionary if the key is not contained. I get an error when adding it, it says that the key is already in the dictionary. I guess that the key was added by a parallel process after the .Contains check of this thread, but before the add. Other than placing that line in a try-catch, is there another simple solution I can use to prevent that error?

Parallel.ForEach(branchFixes, b =>
{
  Parallel.ForEach(b.Value, t =>
  {
    var team = t.Key;
    if (!resultTeamDict.ContainsKey(team))
    {
      resultTeamDict.Add(team, new Dictionary<FixItem, Dictionary<BranchInfo, bool>>());
    }
  });
});
like image 831
Amaranth Avatar asked Apr 01 '14 15:04

Amaranth


2 Answers

I see some suggestions for ConcurrentDictionary. Just be carefull about optimization and performance issues. There's a difference between Dictionary and ConcurrentDictionary RunTime Complexity on inserting and reading data (it may go to 10 times slower with ConcurrentDictionary)

like image 126
Bechir Anoir Chabchoub Avatar answered Sep 25 '22 19:09

Bechir Anoir Chabchoub


Even aside from your race condition, Dictionary<,> isn't thread-safe. You should be using ConcurrentDictionary<,> and in this case probably the AddOrUpdate method to perform the modification atomically. (I assume that you want to add a value to the "nested" dictionary too. Otherwise, consider TryAdd.)

like image 30
Jon Skeet Avatar answered Sep 23 '22 19:09

Jon Skeet