The other day we had to add a longer running I/O call during a log in process that already took a while and I was asked to ensure that we do not add any more additional time to the log in process. I recalled using delegates to speed up some data access to some FoxPro databases a couple years back when I was at SRG J
Basically, let’s say you have a simple little program that does some adding and then does some multiplying. To make it interesting we’ll make each method take 10 seconds.
It looks like this:
static void Main(string[] args)
{
DateTime start = DateTime.Now;
int addresult = AddTwoNumbers(2, 3);
int multiplyResult = MultiplyTwoNumbers(2, 3);
DateTime finish = DateTime.Now;
TimeSpan resultTime = finish - start;
Console.WriteLine("Add Result = {0}, Multiply Result = {1}, Time To Run = {2}", addresult, multiplyResult, resultTime);
Console.WriteLine("press a key to exit");
Console.ReadKey();
}
public static int AddTwoNumbers(int parm1, int parm2)
{
for (int x = 0; x < 10; x++)
{
Thread.Sleep(1000);
Console.WriteLine("AddTwoNumbers waiting");
}
return parm1 + parm2;
}
public static int MultiplyTwoNumbers(int parm1, int parm2)
{
for (int x = 0; x < 10; x++)
{
Thread.Sleep(1000);
Console.WriteLine("MultiplyTwoNumbers waiting");
}
return parm1 * parm2;
}
Basically it runs sequentially first adding two numbers after counting to 10 then multiplying two numbers while counting to 10. The output looks like this and takes about 20 seconds to run J

Let’s now convert this over to adding delegates. Our methods have a signature of int [name](int, int) so we’ll have to make a delegate with the same signature. For clarity in my code I always make a delegate type specific to each method type.
public delegate int AddTwoNumbersDelegate(int parm1, int parm2);
public delegate int MultiplyTwoNumbersDelegate(int parm1, int parm2);
then I’ll add a couple lines to my main function. It’ll look like this:
AddTwoNumbersDelegate addDelegate = new AddTwoNumbersDelegate(AddTwoNumbers);
MultiplyTwoNumbersDelegate multiplyDelegate = new MultiplyTwoNumbersDelegate(MultiplyTwoNumbers);
That just creates the delegate. So now if I call addDelegate(2,2); it will delegate over to MultiplyTwoNumbers(2,2); but the COOL thing with delegates is you automatically get the Async Pattern built into them. So let’s add some code to fire off both of these delegates asynchronously:
IAsyncResult addIar = addDelegate.BeginInvoke(2, 3, null, null);
IAsyncResult multiplyIar = multiplyDelegate.BeginInvoke(2, 3, null, null);
Ok, what are these nulls? Well the first null is the AsyncCallback reference… this we would pass in another delegate with a specific format. When the asynchronous operation finishes, it will execute the call back delegate and pass in a reference to an IAsyncResult implementation. The second is an object reference where we can pass in state. I’ll show you some tricks we can do with that some day.
For now, ignore both of these parameters because we’re going to block the thread right after we start these invocations. BeginInvoke is non-blocking… meaning that after you call BeginInvoke another thread is fired up and begins working the invocation off the thread pool but your main app thread continues on to the next statement (another BeginInvoke call).
So anyhow, now we have 2 threads working at the same time and we want to block the app thread to wait for both of them to exit (Synchronize the two worker threads). This is the simplest way to synch threads… but not always ideal (see WaitHandle, AutoResetEvent, ManualResetEvent, Mutex, Semaphore, ReaderLock and WriterLock for other ideas about how to sync threads)
So here’s our thread blocking calls:
/*int*/ addresult = addDelegate.EndInvoke(addIar);
/*int*/ multiplyResult = multiplyDelegate.EndInvoke(multiplyIar);
Then we wrap this all up with a console.writeline… here’s the whole final app:
class Program {
static void Main(string[] args)
{
DateTime start = DateTime.Now;
int addresult = AddTwoNumbers(2, 3);
int multiplyResult = MultiplyTwoNumbers(2, 3);
DateTime finish = DateTime.Now;
TimeSpan resultTime = finish - start;
Console.WriteLine("Add Result = {0}, Multiply Result = {1}, Time To Run = {2}", addresult, multiplyResult, resultTime);
Console.WriteLine("To begin the async press any key");
Console.ReadKey();
start = DateTime.Now;
AddTwoNumbersDelegate addDelegate = new AddTwoNumbersDelegate(AddTwoNumbers);
MultiplyTwoNumbersDelegate multiplyDelegate = new MultiplyTwoNumbersDelegate(MultiplyTwoNumbers);
IAsyncResult addIar = addDelegate.BeginInvoke(2, 3, null, null);
IAsyncResult multiplyIar = multiplyDelegate.BeginInvoke(2, 3, null, null);
addresult = addDelegate.EndInvoke(addIar);
multiplyResult = multiplyDelegate.EndInvoke(multiplyIar);
finish = DateTime.Now;
resultTime = finish - start;
Console.WriteLine("Add Result = {0}, Multiply Result = {1}, Time To Run = {2}", addresult, multiplyResult, resultTime);
Console.WriteLine("press any key to exit");
Console.ReadKey();
}
public static int AddTwoNumbers(int parm1, int parm2)
{
for (int x = 0; x < 10; x++)
{
Thread.Sleep(1000);
Console.WriteLine("AddTwoNumbers waiting");
}
return parm1 + parm2;
}
public static int MultiplyTwoNumbers(int parm1, int parm2)
{
for (int x = 0; x < 10; x++)
{
Thread.Sleep(1000);
Console.WriteLine("MultiplyTwoNumbers waiting");
}
return parm1 * parm2;
}
}
public delegate int AddTwoNumbersDelegate(int parm1, int parm2);
public delegate int MultiplyTwoNumbersDelegate(int parm1, int parm2);
