Understanding async against callback

Published:

While learning the new asynchrony feature in C# 5.0, I was experimenting the difference between the previous method of achieving asynchrony using callback against the latest feature provided by C# by utilizing the async and await keyword. So what's the difference?

This question raised againt when I was browsing SO. So I thought I would discuss it here. Besides the internal implementation difference by MS (based on my reading, async and await does not utilize threading, the flow of the code actually changes.

Consider the following code:

static void Main(string[] args)
{
    MakeRequest();       

    Console.ReadLine();
}

private static async void MakeRequest()
{
    await UseHttpClient();
    UseWebClient();
}

private static async Task UseHttpClient()
{
    Console.WriteLine("=== HttpClient ==");
    var client = new HttpClient();
    var request = new HttpRequestMessage(HttpMethod.Get, new Uri("http://www.google.com"));
    Console.WriteLine("HttpClient requesting...");
    var response = await client.SendAsync(request);
    Console.WriteLine(response.Content.ReadAsStringAsync().Result.Substring(0,100));
    Console.WriteLine("HttpClient done");
}

private static void UseWebClient()
{
    Console.WriteLine("=== WebClient ==");
    var webClient = new WebClient();
    webClient.DownloadStringAsync(new Uri("http://www.google.com"));
    Console.WriteLine("WebClient requesting...");
    webClient.DownloadStringCompleted += (sender, eventArgs) => Console.WriteLine(eventArgs.Result.Substring(0,100));
    Console.WriteLine("WebClient done.");
}

You might guess that both would output the same result, right? Apparently no.

Output:

=== HttpClient ==
HttpClient requesting...
<!doctype html><html itemscope="itemscope" itemtype="http://schema.org/WebPage">
<head><meta itemprop
HttpClient done

=== WebClient ==
WebClient requesting...
WebClient done.
<!doctype html><html itemscope="itemscope" itemtype="http://schema.org/WebPage">
<head><meta itemprop

When you have await keyword, what it does is that it returns back to the caller of the method, thus any code after the await keyword does not actually get executed yet because it await for the result. It is different from the callback method. In term of flow of code, you might agree that the new feature of await makes the code flows better. You no longer have 'jump' to certain part of code as the callback is called.

Callback method is still okay to use, in fact there are still .Net libraries aren't updated yet to support the new feature. For example, the WebClient still utilize the callback method. To make it asynchronous, you would have to do some sort of threading, which is pretty pain in the neck. Another easier way is to create a method utilizing the TaskCompletionSource. If you google around, this has been covered a lot.

This is a useful source for it:

  1. StackOverflow discussion
  2. Stephen Cleary's blog