HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Is Concurrent Collection Needed Here?

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
concurrentcollectionhereneeded

Problem

I'm playing around with switching some code to using Parallel.ForEach and I have a question about whether I need to be concerned about the effects of concurrency here. Here's a simplified version of what I'm doing:

public IList RetrieveAllItems(int paramValue)
{
    var itemFuncs = new List>>
                {
                    RetrieveItems1,//one method to retrieve items, taking an int param
                    RetrieveItems2//another one that takes an int param
                };

    List allItems = new List();

    Parallel.ForEach(itemFuncs, (f) =>
                {
                    //is this a problem?
                    allItems.AddRange(f(paramValue));
                });

    return allItems;
}


For this application, I do not care about the order that my Item objects are added to allItems (in fact, I do explicit ordering later on). My question is whether I could get into trouble here with both functions attempting to add Item objects at the same time.

My motivation for playing around with this is simply to try to speed up this sequence of events, and when I tried using a BlockingCollection instead, my timings, obviously slowed down to the point that there was hardly any difference between doing these two operations in parallel versus the old, serial way. When I use a simple List then I do see impressive speed-ups.

So, considering I am just adding objects to a collection in a parallel fashion, is using a non-thread safe collection asking for trouble here? My real-world experience with multi-threaded/parallel programming is very sparse, hence the uncertainty here.

Solution

Yes, what you are doing is a problem. List is not thread-safe and adding items from multiple threads can lead to data corruption (for example individual elements overwriting each other).

You said that you don't care about the order of items inserted quickest fix is to use ConcurrentBag

Another option is to the PLINQ extensions and use the Select extension of the ParallelQuery. The code would look like this:

return itemFuncs.AsParallel().SelectMany(f => f(paramValue)).ToList();

Code Snippets

return itemFuncs.AsParallel().SelectMany(f => f(paramValue)).ToList();

Context

StackExchange Code Review Q#38197, answer score: 8

Revisions (0)

No revisions yet.