I was doing some work recently on a demo application where data was being pulled in from multiple locations and being added to a collection that was also being iterated over in the same method.  Because this data was arriving on multiple threads (i.e. async network call backs for example) I’d occasionally see the usual “collection was modified” error messages indicating that another thread had altered the collection while the first was iterating over it.  Obvious threading bug, #FacePlam applied.

While it can be complex at times to find these kinds of errors, in this case it was fairly easy to diagnose and fix, so following good bug fix practices I took the standard approach of writing a test to prove the bug exists, fixing the code and then running the test again to prove it’s fixed.

Now, it should be noted that testing threading issues in a deterministic way is nigh on impossible, and there is no guarantee that a unit test for threading issues will genuinely prove the code bug free, however the approach taken here was good enough to throw the threading exception each and every time I ran the test and also the throw the exception on the build server.

Here’s the code:

[TestMethod]
public void ThreadingFun()
{
InitializeControllerAndGroup();

Task[] tasks = new Task[10]
{
Task.Factory.StartNew(() => MakeMove(1)),
Task.Factory.StartNew(() => MakeMove(2)),
Task.Factory.StartNew(() => MakeMove(1)),
Task.Factory.StartNew(() => MakeMove(2)),
Task.Factory.StartNew(() => MakeMove(1)),
Task.Factory.StartNew(() => MakeMove(2)),
Task.Factory.StartNew(() => MakeMove(1)),
Task.Factory.StartNew(() => MakeMove(2)),
Task.Factory.StartNew(() => MakeMove(1)),
Task.Factory.StartNew(() => MakeMove(2)),
};
Task.WaitAll(tasks);
}
Ignore the first line, that’s just where the collection is being initialised.  Also ignore the fact that there’s no Assert statements in this code.  The test passes if we have no threading exceptions thrown and fails if we have one.

The important thing here is to see how easy it is to fire off a lot of threads in a single, easy to read unit test without all the usual threading plumbing code that would litter something like this.

The way it works is that we define a set of tasks via the Task Parallel Library (part of .NET 4.0) each of which calls the code where we have our threading problem.  When Task.Factory.StartNew() is called the Task Parallel Library (TPL) immediately creates a new thread and calls the method returning control to our code along with a Task object so would can check the state of the task or cancel it if so desired.  In this case we don’t care and immediately start another thread as soon as possible.

We then use the Task.WaitAll statement to wait until all the Tasks we defined are completed so that the test doesn’t complete prematurely.  Too easy.

Note that we could also just as easily have used Parallel.Invoke for this.  The same test using Parallel Invoke would be something like this:

[TestMethod]
public void ParallelInvoke()
{
InitializeControllerAndGroup();

Parallel.Invoke(
() => MakeMove(1),
() => MakeMove(2),
() => MakeMove(1),
() => MakeMove(2),
() => MakeMove(1),
() => MakeMove(2),
() => MakeMove(1),
() => MakeMove(2),
() => MakeMove(1),
() => MakeMove(2)
);
}
I personally prefer the first approach because I like the more explicit control over the thread creation, though it’s obviously noisier than the Parallel.Invoke version.  Note that with Parallel.Invoke you hand over control to the TPL and it figures out how many threads it will use to run the actions you define based on the number of cores available on the machine.

Regardless of the method you choose you can take advantage of the TPL to help you unit test your multithreaded code and make your application more resilient.