The smallest change in your application can make all the difference. I was just playing around with some ideas and boom I found something awesome. Now I have been using the Task Parallel Library (TPL) for a long time but I've never used the Parallel.For or Parallel.ForEach loops. I was so excited when I found these APIs. Let's take a look.

var items = new []{ 1, 2, 3, 4, 5, 6 };
var watch = Stopwatch.StartNew();

foreach (var item in items) {
    Console.WriteLine(item);
    Thread.Sleep(100);
}

Console.Write(watch.Elapsed);

As expected this loop takes around 600 ms and prints out 1,2,3,4,5,6. Now let's see what happens if we switch this over to using a Parallel.ForEach loop.

var items = new []{ 1, 2, 3, 4, 5, 6 };
var watch = Stopwatch.StartNew();

Parallel.ForEach(items, item => {
    Console.WriteLine(item);
    Thread.Sleep(100);
});

Console.Write(watch.Elapsed);

Now when we run this code and average around 130 ms and it prints out... a random order.

Being that the loop is parallel (aka multi-threaded) then we are not guaranteed a specific order.

Now don't let order deter you from using the parallel loops. There are many loops that do not require any specific order and would greatly benefit from parallel processing. The TPL provides "simple" parallel processing without the headache of managing a bunch of threads yourself. You can also go from single threaded processing to parallel processing then right back to single threaded processing without a bunch of crazy code.

I previously said the TPL provides a "simple" way to do parallel processing. This does not mean that parallel processing is "easy".

It is still up to you to properly implement the processing in a way that is thread safe.

Let's look at the same loops but using For. Here is another normal everyday for loop.

var items = new []{ 1, 2, 3, 4, 5, 6 };
var watch = Stopwatch.StartNew();

for (var i = 0; i < items.Length; i++) {
    Console.WriteLine(items[i]);
    Thread.Sleep(100);
}

Console.Write(watch.Elapsed);

Again it takes approximately 600 ms and prints out 1, 2, 3, 4, 5, 6. Now for the Parallel.For version.

var items = new []{ 1, 2, 3, 4, 5, 6 };
var watch = Stopwatch.StartNew();

Parallel.For(1, items.Length + 1, i =>  {
    Console.WriteLine(i);
    Thread.Sleep(100);
});

Console.Write(watch.Elapsed);

The parallel version again averages out to around 120 ms and prints the numbers out in a random order.

You can see in these examples that both parallel version perform much better and take advantage of todays multi-processor systems. You'll need to examine your loop to determine if it could benefit from parallel processing. Just remember that not all loops will perform better in parallel. As a matter of fact some could perform worse.

The next time you start writing that for loop check and see if you could take advantage of the Task Parallel Library.

Rock on and Become Epic!