ParallelApply: Distribute Calculations Over Multicore / Processors

This code applies a BackgroundFunction to elements of an IEnumerable using the ThreadPool. If you don’t know what that means, it’s probably not of interest to you:

   10     delegate void BackgroundFunction(object memberOfEnumerable);

   11 

   12     class Program

   13     {

   14         static void Main(string[] args)

   15         {

   16             int[] nums = new int[100];

   17             for (int i = 0; i < 100; i++)

   18             {

   19                 nums[i] = i;

   20             }

   21 

   22             Random r = new Random();

   23             BackgroundFunction func = delegate(object memberOfEnumerable)

   24             {

   25                 int i = (int) memberOfEnumerable;

   26                 Thread.Sleep(r.Next(1000));

   27                 Console.WriteLine(i);

   28             };

   29 

   30             ParallelApply(nums, func);

   31             Console.ReadKey();

   32         }

   33 

   34         static void ParallelApply(IEnumerable enumerable, BackgroundFunction function)

   35         {

   36             ManualResetEvent done = new ManualResetEvent(false);

   37             int doneRefCount = 1;

   38 

   39             BackgroundFunction wrappedBlock = delegate(object state)

   40             {

   41                 function.DynamicInvoke(state);

   42                 int isDone = Interlocked.Decrement(ref doneRefCount);

   43                 if (isDone == 0)

   44                 {

   45                     done.Set();

   46                 }

   47             };

   48 

   49             WaitCallback callback = new WaitCallback(wrappedBlock);

   50             foreach (object o in enumerable)

   51             {

   52                 Interlocked.Increment(ref doneRefCount);

   53                 ThreadPool.QueueUserWorkItem(callback, o);

   54             }

   55             int isDoneLate = Interlocked.Decrement(ref doneRefCount);

   56             if (isDoneLate == 0)

   57             {

   58                 done.Set();

   59             }

   60             done.WaitOne();

   61         }

   62     }