Click here to Skip to main content
13,446,762 members (40,881 online)
Click here to Skip to main content
Add your own
alternative version


31 bookmarked
Posted 4 Feb 2009

Poor Man's Parallel.ForEach Iterator

, 4 Feb 2009
Rate this:
Please Sign up or sign in to vote.
Parallel Task Library when released with .NET 4.0 will be great, until then here is a simple .NET 3.0 Parallel.ForEach for the rest of us.


How about a simple parallel ForEach iterator that works with .NET 3.0 until Task Parallel Library is available with .NET 4.0.


Task Parallel Library (TPL) will certainly help developers squeeze every bit of processing power out of their hardware, however Microsoft does not offer TPL for .NET 3.0 or .NET 3.5. TPL and Parallel LINQ will be offered as part of .NET 4.0. Until Microsoft releases .NET 4.0 or developers upgrade their development environments, here is a “Poor Man’s Parallel.ForEach” for the rest of us.

There is vast amount of literature about parallel processing, however in a nutshell I will try to explain the motivation for this code and offer my warnings: Reasonably priced laptops come with two CPU cores and average Windows servers have eight CPU cores. Even if you have ten thousand elements to iterate, a serial iteration such as foreach, while or for can only utilize single core where all the other cores are idling. If a particular procedure doesn't need to access objects that constantly share state, spreading processing over multiple threads provides proven performance gains. Being careful about objects sharing state is utterly important, if a coder blindly starts converting traditional serial iterations to parallel iterations; results will not be any different than giving a chain-saw to an 8 year old.

Using the Code

The usage is of the code is exactly as in TPL. Very simple and concise:

// Sample usage:   
var orders = GetOrders();
   Parallel.ForEach(orders, order => {


I used asynchronous delegate invocation. Begin/End pattern is relatively simple to read and maintain. There is possibly an overhead using delegates over using System.Threads. Let me know how you can improve this code. I am looking forward to hear your comments.

public class Parallel
        public static int NumberOfParallelTasks;
        static Parallel()
            NumberOfParallelTasks = Environment.ProcessorCount;  

        public static void ForEach<T>(IEnumerable<T> enumerable,Action<T> action)
            var syncRoot = new object();

            if (enumerable == null ) return;

            var enumerator = enumerable.GetEnumerator();
            InvokeAsync<T> del = InvokeAction;
            var seedItemArray = new T[NumberOfParallelTasks];
            var resultList = new List<IAsyncResult>(NumberOfParallelTasks);

            for (int i = 0; i < NumberOfParallelTasks; i++)
                bool moveNext;
                lock (syncRoot)
                    moveNext = enumerator.MoveNext();
                    seedItemArray[i] = enumerator.Current;
                if (moveNext)
                    var iAsyncResult= del.BeginInvoke
		     (enumerator, action, seedItemArray[i], syncRoot,i, null,null);
            foreach(var iAsyncResult in resultList)

        delegate void InvokeAsync<T>(IEnumerator<T> enumerator, 
		Action<T> achtion, T item, object syncRoot,  int i);

        static void InvokeAction<T>(IEnumerator<T> enumerator,Action<T> action,
				T item,object syncRoot,int i )
                Thread.CurrentThread.Name = 
			String.Format("Parallel.ForEach Worker Thread No:{0}", i);
            bool moveNext=true;

            while (moveNext)
                lock (syncRoot)
                    moveNext = enumerator.MoveNext();
                    item = enumerator.Current;


There is always room for improvement. After publishing this article, I dug up other articles about BeginInvoke. Calling EndInvoke and AsyncWaitHandel.Close() is suggested not to leave garbage collection to chance. I tested it and it works fine and I didn't see performance overhead.

foreach (var iAsyncResult in resultList)iAsyncResult.AsyncWaitHandle.WaitOne();

The above changed to the following code:

foreach(var iAsyncResult in resultList)


  • 4th February, 2009: Initial post


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Emre Aydinceren
Architect Harley-Davidson
United States United States
Architect of Harley-Davidson's United States dealer's dealership management system.

You may also be interested in...


Comments and Discussions

PraiseWorking in SSIS for SQL2008R2 Pin
Matthew Crawford4-Oct-16 23:47
memberMatthew Crawford4-Oct-16 23:47 
QuestionDoes it come in a V-Twin? Pin
TheArchitectmc29-Dec-09 9:21
memberTheArchitectmc29-Dec-09 9:21 
GeneralPower Threading Library Pin
wallism10-Feb-09 19:25
memberwallism10-Feb-09 19:25 
Nice article but if you are doing any form of multi threaded processing you have to check out the Power Threading library.[^]

It's free and written by Jeffrey Richter, basically the definitive guru on multi threaded programming (amongst other things) and there is a great video with Jeffrey showing how it works and how to use it.

The very interesting thing about it is it allows you to write asynchronous code in a "synchronous" manner. Also means you don't need to use any nasty 'lock' statements Smile | :)
QuestionDoes the parrallel.For chop up the work in an optimal way or is it better to do this explicitly? Pin
Nigel-Findlater9-Feb-09 20:15
memberNigel-Findlater9-Feb-09 20:15 
AnswerRe: Does the parrallel.For chop up the work in an optimal way or is it better to do this explicitly? Pin
Emre Aydinceren10-Feb-09 4:02
memberEmre Aydinceren10-Feb-09 4:02 
GeneralProgram error [modified] Pin
Frank Willett6-Feb-09 7:58
memberFrank Willett6-Feb-09 7:58 
AnswerRe: Program error Pin
Emre Aydinceren8-Feb-09 17:48
memberEmre Aydinceren8-Feb-09 17:48 
GeneralRe: Program error Pin
Frank Willett9-Feb-09 8:48
memberFrank Willett9-Feb-09 8:48 
QuestionMultiple cores? Pin
Josh Fischer5-Feb-09 2:39
memberJosh Fischer5-Feb-09 2:39 
QuestionMight this be a problem with too many threads? Pin
argyler4-Feb-09 21:40
memberargyler4-Feb-09 21:40 
AnswerRe: Might this be a problem with too many threads? Pin
assmax5-Feb-09 1:11
memberassmax5-Feb-09 1:11 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01-2016 | 2.8.180318.2 | Last Updated 4 Feb 2009
Article Copyright 2009 by Emre Aydinceren
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid