using System; using System.Collections; using System.Collections.Generic; using System.Text; using System.Threading; namespace Utilities { public delegate void ForDelegate(int i); public delegate void DelegateProcess(); // Based on: // http://coding-time.blogspot.pt/2008/03/implement-your-own-parallelfor-in-c.html // C# 2.0 adaptation based on: // http://dotnetgalactics.wordpress.com/2009/11/19/how-to-provide-a-parallel-for-loop-in-c2-0-2/ public class Parallel { /// /// Parallel for loop. Invokes given action, passing arguments /// fromInclusive - toExclusive on multiple threads. /// Returns when loop finished. /// public static void For(int fromInclusive, int toExclusive, ForDelegate forDelegate) { int chunkSize = 4; For(fromInclusive, toExclusive, chunkSize, forDelegate); } /// /// Parallel for loop. Invokes given action, passing arguments /// fromInclusive - toExclusive on multiple threads. /// Returns when loop finished. /// /// /// chunkSize = 1 makes items to be processed in order. /// Bigger chunk size should reduce lock waiting time and thus /// increase paralelism. /// public static void For(int fromInclusive, int toExclusive, int chunkSize, ForDelegate forDelegate) { int threadCount = Environment.ProcessorCount; For(fromInclusive, toExclusive, chunkSize, threadCount, forDelegate); } /// /// Parallel for loop. Invokes given action, passing arguments /// fromInclusive - toExclusive on multiple threads. /// Returns when loop finished. /// /// /// chunkSize = 1 makes items to be processed in order. /// Bigger chunk size should reduce lock waiting time and thus /// increase paralelism. /// /// number of process() threads public static void For(int fromInclusive, int toExclusive, int chunkSize, int threadCount, ForDelegate forDelegate) { int index = fromInclusive - chunkSize; // locker object shared by all the process() delegates object locker = new object(); // processing function // takes next chunk and processes it using action DelegateProcess process = delegate() { while (true) { int chunkStart = 0; lock (locker) { // take next chunk index += chunkSize; chunkStart = index; } // process the chunk // (another thread is processing another chunk // so the real order of items will be out-of-order) for (int i = chunkStart; i < chunkStart + chunkSize; i++) { if (i >= toExclusive) return; forDelegate(i); } } }; // launch process() threads IAsyncResult[] asyncResults = new IAsyncResult[threadCount]; for (int i = 0; i < threadCount; ++i) { asyncResults[i] = process.BeginInvoke(null, null); } // wait for all threads to complete for (int i = 0; i < threadCount; ++i) { process.EndInvoke(asyncResults[i]); } } } }