Basic Asynchronous Programming with Delegates

There are a few ways to do asynchronous programming with .NET. Besides using the BackgroundWorker component and using the Thread class, we can use delegates to make asynchronous calls to any method.

If you’re familiar with calling BeginXXX, say, to execute a web service method, this article will seem very familiar. There are three ways to make calls asynchronously. The main steps involved in all three are: create a delegate for the method you want to execute, create an instance of that delegate using the method as a parameter, call delegate.BeginInvoke. From there onwards, the three methods differ slightly.

We’ll start will a simple, pretty redundant method, which returns an upper case version of a string we provide to it:

  1. private string ToUpperCase(string input)
  2. {
  3.     return input.ToUpper();
  4. }

An appropriate delegate would be:

  1. private delegate string
  2.     ToUpperCaseDelegate(string input);

With that in place, we can create our delegate instance wherever we want to call the ToUpperCase method:

  1. ToUpperCaseDelegate del =
  2.     new ToUpperCaseDelegate(ToUpperCase);

To execute the method asynchronously, we’re going to call BeginInvoke:

  1. IAsyncResult result = del.BeginInvoke(
  2.     "hello", null, null);

Here, we’re starting method execution asynchronously and storing an IAsyncResult instance in the variable result. This IAsyncResult is needed so that when we tell the method we’re ready for the result, the method knows which result to give us (the method may have been called multiple times before any results had been retrieved).

We now need to get the result. Based on the above call, there are two ways that we can do this. One is to simply call EndInvoke on the delegate. This will pause execution of the calling thread until a result is obtained:

  1. string upper = del.EndInvoke(result);

Or, we can poll the IsCompleted property of result. If false, we can do something else while we wait. When it’s true, we call EndInvoke as above:

  1. while(!result.IsCompleted)
  2. {
  3.     DoSomethingUseful();
  4. }
  5.  
  6. string upper = del.EndInvoke(result);

The other way to make an asynchronous call is perhaps the preferred way: create a callback method and supply both the callback method and the original delegate to the BeginInvoke method. When the callback is fired, an IAsyncResult instance is passed to it, containing the delegate in IAsyncResult.AsyncState. We simply get a reference to the delegate by casting AsyncState back to the delegate type, and perform the same EndInvoke call as above. The calling code looks like this (note that we don’t need to store the IAsyncResult returned from BeginInvoke as it is passed to the callback method, so we just ignore the fact that BeginInvoke returns anything):

  1. del.BeginInvoke(
  2.     "hello",
  3.     new AsyncCallback(ToUpperCaseCallback),
  4.     del);

The callback method looks like this:

  1. private void ToUpperCaseCallback(
  2.     IAsyncResult result)
  3. {
  4.     ToUpperCaseDelegate del =
  5.     (ToUpperCaseDelegate)result.AsyncState;
  6.     string upper = del.EndInvoke(result);
  7. }

Calling methods asynchronously is fairly easy as long as you understand delegates. They tend to be described as type safe function pointers, which is a fairly good way of thinking about them in my opinion. You just need to create one that matches your method’s signature and hey presto, you can use it to call any method with that signature asynchronously.

Share and Enjoy:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Yahoo! Buzz
  • Twitter
  • Google Bookmarks
  • email
  • LinkedIn
  • Technorati

Leave a Reply

Your email address will not be published. Required fields are marked *