:::: MENU ::::

Wednesday, November 7, 2012


I think that anyone who has ever done any GUI programming for a day-to-day application that empowers people to do their job, regardless of the language or environment, will fully agree with me when I say: “end-users are never satisfied.” End-users do not want to click a button and have their GUI freeze up because your application is crunching data on your main program thread. Enter multi-threading. I do not claim to be anything close to an authority on threading (check outhttp://www.albahari.com/threading/ for everything you’ll ever need to know about C# threading), but I wanted to at least introduce asynchronous web requests because they definitely enhance the end-user experience. Yeah… that’s the story I’m going with anyway, Elliot has been harassing me to actually post here too.

Asynchronous web requests are terribly easy within the .NET framework, someone at Microsoft has already done all of the footwork for us. They wrapped it all up in a WebClient (http://msdn.microsoft.com/en-us/library/system.net.webclient(VS.80).aspx) object, as well.

Lets get started, only minimal code is required to actually implement an asynchronous call. My intention is just to show how to pull down the HTML of a web page, it can be adapted for a lot of other things. Check out the MSDN link (or just mess around with the AutoComplete within Visual Studio) to see what else the WebClient object has to offer.

First, you have to instantiate our WebClient object and setup our event handler for when the DownloadDataAsync call is completed. This is different then the Generic DownloadData call which blocks the main thread until the download is completed. Our call will be better because it will allow the user, for example, to click a button and have their data download on a different thread and be able to do things on main gui thread. Waiting sucks. Code for this is:

using (WebClient asyncWebRequest = new WebClient())
{
    asyncWebRequest.DownloadDataCompleted += asyncWebRequest_DownloadDataCompleted;
    Uri urlToRequest = new Uri("http://www.google.com/");
    asyncWebRequest.DownloadDataAsync(urlToRequest);
}

The only thing left is actually the code in the method that the data/error will return to, and handle any exceptional cases.

void asyncWebRequest_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
 if (e.Error != null)
 {
   MessageBox.Show(e.Error.Message);
   return;
 }

 if (e.Result != null && e.Result.Length > 0)
 {
   string downloadedData = Encoding.Default.GetString(e.Result);
   // do things with data here
 }
 else
 {
   MessageBox.Show("No data was downloaded.");
 }
}

In the end, this functionality enhances the end user experience by not locking up their application while doing background work, and also provides you (the programmer) an easy way to download data in the background without dealing with your own thread. Other considerations may be actually promoting the WebClient to a private variable so you can give the user the option to cancel the request or cancel when the form is closing. This method is meant to be a demonstration of the syntax of a asynchronous call.

More