Click here to Skip to main content
Click here to Skip to main content
Go to top

Action Extensions

, 1 Jul 2008
Rate this:
Please Sign up or sign in to vote.
Parallelization of multicast delegates

Introduction

Ennis Ray Lynch, Jr. gave me an idea the other day in the Lounge. The basic idea was running multicast delegates in parallel.

Background

The code to run delegates in parallel is rather trivial.

static void Run(Action[] aa)
{
  List<IAsyncResult> waits = new List<IAsyncResult>();

  foreach (Action a in aa)
  {
    waits.Add(a.BeginInvoke(null, null));
  }

  foreach (IAsyncResult ar in waits)
  {
    ar.AsyncWaitHandle.WaitOne();
  }
}

To run a multicast delegate in parallel follows the same pattern.

static void Run(Action t)
{
  List<IAsyncResult> waits = new List<IAsyncResult>();

  foreach (Action a in t.GetInvocationList())
  {
    waits.Add(a.BeginInvoke(null, null));
  }

  foreach (IAsyncResult ar in waits)
  {
    ar.AsyncWaitHandle.WaitOne();
  }
}

Using the Code

Following the above pattern, we simply create stubs for the generic Action delegate (only 1 shown for clarity). If needed, you can replace with your own delegate type. There is one important aspect to keep in mind; the delegate MUST return void. Why, you may ask? The answer is simple. There is no easy way to consume multiple return values in C#.

static class ActionExtensions
{
  class WaitList : IDisposable
  {
    readonly List<IAsyncResult> waits = new List<IAsyncResult>();

    public void Add(IAsyncResult ar)
    {
      waits.Add(ar);
    }

    public void Dispose()
    {
      foreach (var ar in waits)
      {
        ar.AsyncWaitHandle.WaitOne();
      }
    }
  }

  public static Action MakeParallel(this Action t)
  {
    return () =>
    {
      using (var w = new WaitList())
      {
        foreach (Action a in t.GetInvocationList())
        {
          w.Add(a.BeginInvoke(null, null));
        }
      }
    };
  }
}

The usage is also trivial. Simply call the MakeParallel extension method.

class Program
{
  static void Main(string[] args)
  {
    Action<int> f = null;

    for (int i = 0; i < 8; i++)
    {
      f += Thread.Sleep;
    }

    Stopwatch ws = Stopwatch.StartNew();

    f(250);

    Console.WriteLine("ser: {0:f3}", ws.Elapsed.TotalMilliseconds);

    f = f.MakeParallel();

    ws = Stopwatch.StartNew();

    f(250);

    Console.WriteLine("par: {0:f3}", ws.Elapsed.TotalMilliseconds);

    Console.ReadLine();
  }
}

The output should show the parallel version running at half (or quarter) the time of the serial version.

Points of Interest

From what I can determine, BeginInvoke utilizes the number of logical CPUs. I have however not been able to test this.

History

  • 2nd July, 2008 - Initial version

License

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

Share

About the Author

leppie
Software Developer
South Africa South Africa
No Biography provided
Follow on   Twitter

Comments and Discussions

 
GeneralNice and simple. PinmvpSacha Barber6-Jan-11 23:15 
I like this. 5
Sacha Barber
  • Microsoft Visual C# MVP 2008-2010
  • Codeproject MVP 2008-2010
Your best friend is you.
I'm my best friend too. We share the same views, and hardly ever argue
 
My Blog : sachabarber.net

GeneralNice, but you should call EndInvoke() PinmemberJelle Hissink6-Jul-08 9:48 
GeneralRe: Nice, but you should call EndInvoke() Pinmemberleppie6-Jul-08 10:20 
GeneralSweet PinmemberNick Butler3-Jul-08 22:28 
GeneralRe: Sweet Pinmemberleppie4-Jul-08 7:21 
GeneralNice work Pinmemberkin3tik2-Jul-08 5:42 
GeneralNice PinmvpPete O'Hanlon1-Jul-08 22:33 
GeneralRe: Nice Pinmemberleppie1-Jul-08 22:48 

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

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

| Advertise | Privacy | Mobile
Web04 | 2.8.140926.1 | Last Updated 2 Jul 2008
Article Copyright 2008 by leppie
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid