I've recently been experimenting with C#'s delegates, and here is an example of how they can be used for multithreading. I've used a ray tracer as a good example of something that can be multithreaded easily. This ray tracer has been grabbed from LukeH's awesome LINQ example here: LukeH's WebLog A Ray Tracer in C# 3.0. I've modified it a bit for my purposes just a little. What i'm trying to accomplish here is getting 4 delegates to render different parts of a scene in simultaneous threads, and stitch them together for one image, and save it to disk. Firstly, you've got to declare a delegate type. It's a little like creating a new enum, in that you're creating a new variable type. This code goes in the class declaration, outside of any functions. In my case, i'm declaring that my delegate has 2 parameters:
delegate void RenderSection(int top, int bottom);
Now i've got my delegate, i want to create my function that fits with the delegate's signature of taking 2 integers:
/// <summary>
/// This is the delegate that renders a part of the image, a delegate for RenderSection
/// </summary>
public void RenderASection(int top, int bottom)
{
  // Raytrace just this section of the scene
  Bitmap SectionBitmap = new Bitmap(width, height);
  RayTracer rayTracer = new RayTracer(width, height,
    (int x, int y, System.Drawing.Color color) =>
      {
        SectionBitmap.SetPixel(x, y, color);
      }
    );
  rayTracer.Render(rayTracer.DefaultScene, top, bottom);

  // Copy my part of the scene into the overall scene
  lock (bitmap)
  {
    Graphics g = Graphics.FromImage(bitmap);
    g.DrawImage(
      SectionBitmap,
      new Rectangle(0, top, width, bottom),
      new Rectangle(0, top, width, bottom),
      GraphicsUnit.Pixel);
  }
}
Okay, now i've got my delegate type and my actual delegate, i want to use them, as i do in my Run function below. Notice that for the 3rd one, i'm using an anonymous delegate for the "Hey: I've finished" callback, for no real reason. The 'CallbackMethod' function is another delegate, matching the signature for the AsyncCallback delegate type.
public void Run()
{
  width = 800;
  height = 800;
  bitmap = new Bitmap(width, height);

  RenderSection myDelegate = RenderASection;

  // Run it with different parameters
  IAsyncResult ar1 = myDelegate.BeginInvoke(0, 200, CallbackMethod, null);
  IAsyncResult ar2 = myDelegate.BeginInvoke(200, 400, CallbackMethod, null);
  IAsyncResult ar3 = myDelegate.BeginInvoke(400, 600,
    delegate(IAsyncResult ar)
      { Console.WriteLine("Section finished (anonymous delegate)"); },
    null);
  IAsyncResult ar4 = myDelegate.BeginInvoke(600, height, CallbackMethod, null);

  // Wait for them to finish
  myDelegate.EndInvoke(ar1);
  myDelegate.EndInvoke(ar2);
  myDelegate.EndInvoke(ar3);
  myDelegate.EndInvoke(ar4);
  
  // Save the output bitmap
  bitmap.Save("RayTrace.png");
}

/// <summary>
/// This is a function we can use as a delegate for AsyncCallback 
/// </summary>
void CallbackMethod(IAsyncResult ar)
{
  Console.WriteLine("Section finished");
}
Here is the entire solution (VS2008): multithreadeddelegatesraytracedemo Cheers, and thanks for reading.

Thanks for reading! And if you want to get in touch, I'd love to hear from you: chris.hulbert at gmail.

Chris Hulbert

(Comp Sci, Hons - UTS)

Software Developer (Freelancer / Contractor) in Australia.

I have worked at places such as Google, Cochlear, Assembly Payments, News Corp, Fox Sports, NineMSN, FetchTV, Coles, Woolworths, Trust Bank, and Westpac, among others. If you're looking for help developing an iOS app, drop me a line!

Get in touch:
[email protected]
github.com/chrishulbert
linkedin



 Subscribe via RSS