C# 5 Async, Part 1: Simplifying Asynchrony – That for which we await
- by Reed
Today’s announcement at PDC of the future directions C# is taking excite me greatly. The new Visual Studio Async CTP is amazing. Asynchronous code – code which frustrates and demoralizes even the most advanced of developers, is taking a huge leap forward in terms of usability. This is handled by building on the Task functionality in .NET 4, as well as the addition of two new keywords being added to the C# language: async and await.
This core of the new asynchronous functionality is built upon three key features. First is the Task functionality in .NET 4, and based on Task and Task<TResult>. While Task was intended to be the primary means of asynchronous programming with .NET 4, the .NET Framework was still based mainly on the Asynchronous Pattern and the Event-based Asynchronous Pattern.
The .NET Framework added functionality and guidance for wrapping existing APIs into a Task based API, but the framework itself didn’t really adopt Task or Task<TResult> in any meaningful way. The CTP shows that, going forward, this is changing.
One of the three key new features coming in C# is actually a .NET Framework feature. Nearly every asynchronous API in the .NET Framework has been wrapped into a new, Task-based method calls. In the CTP, this is done via as external assembly (AsyncCtpLibrary.dll) which uses Extension Methods to wrap the existing APIs. However, going forward, this will be handled directly within the Framework. This will have a unifying effect throughout the .NET Framework. This is the first building block of the new features for asynchronous programming:
Going forward, all asynchronous operations will work via a method that returns Task or Task<TResult>
The second key feature is the new async contextual keyword being added to the language. The async keyword is used to declare an asynchronous function, which is a method that either returns void, a Task, or a Task<T>.
Inside the asynchronous function, there must be at least one await expression. This is a new C# keyword (await) that is used to automatically take a series of statements and break it up to potentially use discontinuous evaluation. This is done by using await on any expression that evaluates to a Task or Task<T>.
For example, suppose we want to download a webpage as a string. There is a new method added to WebClient: Task<string> WebClient.DownloadStringTaskAsync(Uri). Since this returns a Task<string> we can use it within an asynchronous function. Suppose, for example, that we wanted to do something similar to my asynchronous Task example – download a web page asynchronously and check to see if it supports XHTML 1.0, then report this into a TextBox. This could be done like so:
private async void button1_Click(object sender, RoutedEventArgs e)
{
string url = "http://reedcopsey.com";
string content = await new WebClient().DownloadStringTaskAsync(url);
this.textBox1.Text = string.Format("Page {0} supports XHTML 1.0: {1}",
url, content.Contains("XHTML 1.0"));
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Let’s walk through what’s happening here, step by step. By adding the async contextual keyword to the method definition, we are able to use the await keyword on our WebClient.DownloadStringTaskAsync method call.
When the user clicks this button, the new method (Task<string> WebClient.DownloadStringTaskAsync(string)) is called, which returns a Task<string>. By adding the await keyword, the runtime will call this method that returns Task<string>, and execution will return to the caller at this point. This means that our UI is not blocked while the webpage is downloaded. Instead, the UI thread will “await” at this point, and let the WebClient do it’s thing asynchronously.
When the WebClient finishes downloading the string, the user interface’s synchronization context will automatically be used to “pick up” where it left off, and the Task<string> returned from DownloadStringTaskAsync is automatically unwrapped and set into the content variable. At this point, we can use that and set our text box content.
There are a couple of key points here:
Asynchronous functions are declared with the async keyword, and contain one or more await expressions
In addition to the obvious benefits of shorter, simpler code – there are some subtle but tremendous benefits in this approach. When the execution of this asynchronous function continues after the first await statement, the initial synchronization context is used to continue the execution of this function. That means that we don’t have to explicitly marshal the call that sets textbox1.Text back to the UI thread – it’s handled automatically by the language and framework! Exception handling around asynchronous method calls also just works.
I’d recommend every C# developer take a look at the documentation on the new Asynchronous Programming for C# and Visual Basic page, download the Visual Studio Async CTP, and try it out.