Web developers wiki ASP.NET Sitecore Sharepoint Kentico by Evident Interactive

Parallel.For and Parallel.ForEach

Modified: 2011/07/01 17:48 by vanthoog - Categorized as: Csharp
One of the great features in .Net 4.0 is the improved support for multithreading. For example it is much easier now to create loops which use multiple threads. This can be done by using Parallel.For or Parallel.ForEach.

Let’s demonstrate this by using a simple example.

The following example (being a console application) uses a classic for-loop. It loops through a collection of int’s, waits for the specified number of seconds and then displays the specified number. And finally it displays the elapsed time.

using System;
using System.Collections.Generic;
 
namespace ForExample
{
    class Program
    {
        static void Main(string[] args)
        {
            // Define a collection containing waittimes in seconds.
            List waitTimes = new List() { 3, 2, 1 };
 
            System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew();
 
            for (int ii = 0; ii < waitTimes.Count; ii++)
            {
                System.Threading.Thread.Sleep(waitTimesii * 1000); // Sleep takes milliseconds
 
                Console.WriteLine(waitTimesii);
            }
 
            sw.Stop();
 
            Console.WriteLine("It took {0} milliseconds.", sw.ElapsedMilliseconds);
            Console.ReadLine();
        }
    }
}

Here is the output:

3
2
1
It took 6000 milliseconds.

Notice that:
> The numbers are shown in the original order (being 3, 2, 1).
> The elapsed time is 6000 milliseconds, which makes sense because 3 + 2 + 1 = 6 (seconds).

Here is the same example but using Paraller.For instead of the classic for-loop:

using System;
using System.Collections.Generic;
 
namespace ParallerForExample
{
    class Program
    {
        static void Main(string[] args)
        {
            // Define a collection containing waittimes in seconds.
            List waitTimes = new List() { 3, 2, 1 };
 
            System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew();
 
            System.Threading.Tasks.Parallel.For(0, waitTimes.Count, ii =>
                {
                    System.Threading.Thread.Sleep(waitTimesii * 1000); // Sleep takes milliseconds
 
                    Console.WriteLine(waitTimesii);
                });
 
            sw.Stop();
 
            Console.WriteLine("It took {0} milliseconds.", sw.ElapsedMilliseconds);
            Console.ReadLine();
        }
    }
}

And here is the output:

1
2
3
It took 3000 milliseconds.

Notice that:
> The numbers are not shown in the original order. Instead, the order is determined by the waittime (i.e. the smallest waittime first).
> The elapsed time is 3000 milliseconds (being the longest waittime).

This clearly shows the effect of running a loop on multiple threads:
> Things may not be processed in the expected sequence.
> Elapsed time may be reduced significantly.

The same example can also be written using for-each.

Without further explanation here is the same example using a classic for-each loop:

using System;
using System.Collections.Generic;
 
namespace ForEachExample
{
    class Program
    {
        static void Main(string[] args)
        {
            // Define a collection containing waittimes in seconds.
            List waitTimes = new List() { 3, 2, 1 };
 
            System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew();
 
            foreach(int waitTime in waitTimes)
            {
                System.Threading.Thread.Sleep(waitTime * 1000); // Sleep takes milliseconds
 
                Console.WriteLine(waitTime);
            }
 
            sw.Stop();
 
            Console.WriteLine("It took {0} milliseconds.", sw.ElapsedMilliseconds);
            Console.ReadLine();
        }
    }
}

And here is the same example using Parallel.ForEach (without further explanation):

using System;
using System.Collections.Generic;
 
namespace ParallelForEachExample
{
    class Program
    {
        static void Main(string[] args)
        {
            // Define a collection containing waittimes in seconds.
            List waitTimes = new List() { 3, 2, 1 };
 
            System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew();
 
            System.Threading.Tasks.Parallel.ForEach(waitTimes, waitTime =>
                {
                    System.Threading.Thread.Sleep(waitTime * 1000); // Sleep takes milliseconds
 
                    Console.WriteLine(waitTime);
                });
 
            sw.Stop();
 
            Console.WriteLine("It took {0} milliseconds.", sw.ElapsedMilliseconds);
            Console.ReadLine();
        }
    }
}

 © Evident Interactive BV