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
.)
How to add item to dictionary "Parallel loop safe"
-
25-06-2023 - |
سؤال
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>>());
}
});
});
المحلول
نصائح أخرى
You can use the ConcurrentDictionary in .NET 4.5 and replace the ContainsKey and Add method calls with TryAdd. See http://msdn.microsoft.com/en-us/library/dd287191(v=vs.110).aspx
This is a textbook example of a "Time of Check to Time of Use" error: in between the check for whether the dictionary contains the key and the Add
call, another thread might have inserted the item already, invalidating the preconditions of Add
.
The solution is to use a ConcurrentDictionary<T>
or mutually exclude threads from updating the dictionary at the same time via a lock or other synchronization tool.
You might want to profile your code to check whether firing off threads is even worth it--the overhead might be very high in this case.
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)