Phidiax Tech Blog

Adventures in custom software and technology implementation.

Parallel LINQ (PLINQ) Thread Safety - Using AsParallel + List<T>.Add() Returns Object Reference Not Set to an Instance of an Object

Background

I love to develop using PLINQ (Parallel LINQ) for larger data operations as it automates threading behind the scenes which frequently makes more efficient use of the processors available at runtime without having to explicitly control those threads. I recently ran into a pesky issue that finding a solution to was harder than I figured it should be.

I had a situation where I needed to process a list in parallel in which I needed to execute a method on each item, and add the results to a new list. Pretty simple in PLINQ:

List<TypeObject> lstRtn = new List<TypeObject>();

myCollection.AsParallel().ForAll(e => lstRtn.Add(SomeGenericMethod<TypeObject>(e)));

I was inconsistently running into the bane of any developer's existence ("Object Reference Not Set to an Instance of an Object") in the code that made use of the result list. Debugging showed that sometimes items added to the list would be null, and cause this error. Why would they be null?

Short answer: THREAD SAFETY

The generic List is not thread safe, and adding to a list in this manner could result in this sort of "fun" to debug issues.

How To Fix

While we could debate the many solutions for their safety and performance, the .NET framework has this hidden little gem that allows us to add thread safety with a very small change...

//ConcurrentBag is threadsafe for parallel loop, List is not.
System.Collections.Concurrent.ConcurrentBag<TypeObject> lstRtn = new System.Collections.Concurrent.ConcurrentBag<TypeObject>();

myCollection.AsParallel().ForAll(e => lstRtn.Add(SomeGenericMethod<TypeObject>(e)));

This may not be the best performing approach in all instances, but for being able to insert into the list with minimal code changes, this works well. Note that the System.Collections.Concurrent namespace contains a few other collection types that are threadsafe as well.

Loading

Privacy Policy  |  Contact  |  Careers

2009-2017 Phidiax, LLC - All Rights Reserved