Reputation: 5563
I have a collection of items (SortedPoints) that I iterate over using Parallel.ForEach. Each item will become the key in a Dictionary named Stripes. Computing the value for each item is expensive and is in the method BulidStripes.
Parallel.ForEach(SortedPoints, point =>
Stripes[point] = BuildStripes(point, pointToPosition)
);
I can make Stripes a ConcurrentDictionary, but I was wondering if this would work:
1) Make Stripes a regular Dictionary.
2) Iterate over all points serially and fill Stripes with mappings to an empty object.
3) Iterate over all points in parallel and replace the mapping in Stripes with the actual value returned by BuildStripes.
foreach(var point in SortedPoints)
Stripes[point] = emptyStripe;
Parallel.ForEach(SortedPoints, point =>
Stripes[point] = BuildStripes(point, pointToPosition)
);
Is setting the value for a key thread-safe if each thread works on a separate set of keys and each key is pre-loaded into the Dictionary serially as I outlined? I looked at the source code for Dictionary and it looks safe, but these collections are subtle beasts and parallel bugs are hard to spot.
Once the dictionary is created, I never modify it again and all accesses are reads.
Upvotes: 4
Views: 365
Reputation: 17068
Lets see the facts. A thread error can happen if:
Is there any other option? I don't see one. I think you are safe to go with this method.
But just use a regular ConcurrentDictionnary for readibility of course! Perhaps you can gain some performance, but unless you benchmark it, there is no reason to not use a ConcurrentDictionary.
Some docs about what ConcurrentDictionary deal with.
Upvotes: 1