Using Async in C# for easy asynchronous programming

Share on facebook
Share on twitter
Share on linkedin
Share on email

As a programmer there have been many times when I have found a bottle neck in an app I’ve written that comes down to waiting on some kind of input. Usually you end up needing the result of this input for the next step in your code and thus the wait is necessary. However in some special cases (such as downloading a set of images), the inputs are not interconnected and therefore can be done concurrently. Normally this would mean learning and implementing some sort of multithreaded paradigm, which are usually tedious and fraught with risk.

However, as of .NET version 4.5, you can now use the simple and easy to use async keyword to modify your existing code to speed it up with the power of multithreading without making your code unreadable nor adding a lot of extra syntax.

For example consider this simple piece of code that fetches three images:

static void Main(string[] args)
{
    var microsoftLogo =
        GetImage(
            "http://c.s-microsoft.com/en-us/CMSImages/mslogo.png?version=856673f8-e6be-0476-6669-d5bf2300391d");
    var googleLogo =
        GetImage("https://www.google.com/images/srpr/logo11w.png");
    var yahooLogo =
        GetImage("https://s.yimg.com/nn/img/yahoo-logo-201402200629.png");

    Console.WriteLine(
        String.Format("Retrieved {0} total bytes.", microsoftLogo.Length + googleLogo.Length + yahooLogo.Length));
    Console.ReadKey();
}

static byte[] GetImage(string imageUrl)
{
    var client = new WebClient();
    byte[] data = client.DownloadData(imageUrl);
    Console.WriteLine(String.Format("Retrieved {0}.", imageUrl));
    return data;
}

 

This code will get the Microsoft logo first, and then the Google logo, and then finally the Yahoo logo. But with a few small tweaks we can make them retrieve at the same time:

static void Main(string[] args)
{
       var microsoftLogoTask =
               GetImage( 
                     "http://c.s-microsoft.com/en-us/CMSImages/mslogo.png?version=856673f8-e6be-0476-6669-d5bf2300391d");
        var googleLogoTask =
             GetImage("https://www.google.com/images/srpr/logo11w.png")
        var yahooLogoTask = 
             GetImage("https://s.yimg.com/nn/img/yahoo-logo-201402200629.png");

        var microsoftLogo = microsoftLogoTask.Result;
        var googleLogo = googleLogoTask.Result;
        var yahooLogo = yahooLogoTask.Result;

       Console.WriteLine(
              String.Format("Retrieved {0} total bytes.", microsoftLogo.Length + googleLogo.Length + yahooLogo.Length));
       Console.ReadKey();
}

static async Task<byte[]> GetImage(string imageUrl)
{
        var client = new WebClient();
        byte[] data = client.DownloadData(imageUrl);
        Console.WriteLine(String.Format("Retrieved {0}.", imageUrl));
        return data;
}

Now we’re retrieving these images asynchronously! They may come back in the same order, but they may not. The three calls to GetImage now kick off a download of each image without waiting for the image to actually finish, but the program will only finish when all 3 are retrieved. The key to this is using the Result property. This tells our program that the system now needs the value that the asynchronous function is already in the process of retrieving and waits until the function truly returns the value.

As in any multithreading model, we still have some basic considerations to keep in mind such as resource sharing and deadlocks, but with some forethought these problems are solvable, and with .NET 4.5, adding concurrency to your app is as simple as adding a few special keywords!

For more information on this topic, please see Microsoft’s documentation on async, and its partner keyword await.

No Comments

Leave a Comment

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