C# 5 Async, Part 1: Simplifying Asynchrony – That for which we await
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")); }
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.
Does this imply that your main threads will have to know to wait for these async executions to complete at some stopping point? In your example above, if this were within an ASP.NET page, what if the timeout is set to a few minutes and the http call timed out? I would imagine that the rest of the page will finish its postback events, and then ended up rendering the textbox without the result of the webclient, is this correct?
Are there only specific contexts in which you can use this?
Other than this scenario… it makes perfect sense for a silverlight/wpf/windows phone 7 application.
You could use this in other contexts. There’s also a whole framework for cancellation tied to tasks, etc. I’ll go into more detail over time to show some of these issues. Granted, if you wanted to use this in an ASP.NET page, at some point, you’d probably wait on the async task explicitly (with a timeout, of course) to get your result. The internal code to fetch this can be async, but at some point, you’d likely wait on the Task.Result, which blocks.
Great to see C# will get better support for asynchronous programming in the future but it is a bit odd to say that this “frustrates and demoralizes even the most advanced of developers” when we have been using the same approach in F# for 3 years and in OCaml for at least 8 years!
Jon,
I agree completely – I was, of course, thinking of C# (and VB.NET) developers here – not necessarily other languages. Many other languages have tackled this problem with varied levels of success. F# and OCaml are two great examples (though I would disagree – they use a slightly different approach), but C# and VB.NET developers have been fighting with this, painfully, for a while now. You can even see it in the .NET Framework – the BCL keeps changing guidance and patterns (APM/EAP/etc) because it’s always been painful.
Here’s an explanation about async and ASP.NET:
http://evolpin.wordpress.com/2011/05/02/c-5-await-and-async-in-asp-net/
Amazing stuff. The new integrated asynchronous features sound exciting and appear simple enough to be used by the average C# programmer in process-intensive apps that are GUI-based. No more frozen dialogs! Btw, isn’t it “that which we await” or “that for which we wait”? Sorry, it just seemed like a minor detraction to an otherwise excellent article! Thanks.
Sebeshan: I agree, “that for which we wait” is more correct, but I wanted to play up “await” 😉
This article is over a year old, but for what it’s worth, what Sabeshan meant is that the title is grammatically incorrect. As he said, it’s either “that which we await†or “that for which we waitâ€, and since you wanted to coin in the “await” pun, then you’ll want the first one. You await something, and wait *for* something, but don’t await *for* something.