Developer

Why .NET developers should check out the await system

The new await keyword in the Async CTP makes it easier to write asynchronous code, so processes that can take up time no longer jam up the application's UI.

Jason Rainwater, a C# and WPF expert, spoke at the Columbia Enterprise Developer Guild meeting in early February about asynchronous programming in .NET. He gave a good history of asynchronous programming in .NET, and showed off a class called WorkerQueue that makes it pretty easy to asynchronously run code that interacts with the UI thread (historically, this has been an annoyance). He finished his presentation with something that I've been paying attention to lately: the new await keyword in the Async CTP and scheduled for C# 5.

The new await system is interesting because it allows you to run code that does not block the main UI thread, but at the same time can update the main UI thread. For anyone who has messed around with systems like BackgroundWorker, you know this is a real headache. And because the structure is built on Tasks (from .NET 4's Parallel Extensions Library), you get access to built-in functionality such as cancellation.

It's pretty easy to use the await system. If you want a method to run asynchronously, you mark it with the async keyword after its scope declaration, and you make at least one call within it using the await keyword. When you use await, it must be to a method that supports it. Out of the box, you get a couple of simple methods (such as WebClient.DownloadStringAsync) that support await. The method that is asynchronous can return void, Task, or Task<TResult>. If you choose to return a result using Task<TResult>, the compiler will do it automatically for you.

Here's a code sample:

private async void AsyncMethod() {

mainWindow.Control.Property = await GetDataAsync();

}

This code assumes you've made a GetDataAsync() method that supports await. When the await call is run, it checks to see if the GetDataAsync method has a result yet (remember, it uses Task under the hood). If the GetDataAsync method has a result, it returns it and keeps moving. If the GetDataAsync method doesn't have a result, it essentially allows control to return to the UI thread, keeping the application responsive, while the work is performed in a separate thread. There is a lot more to the details than what I've summarized, but it's enough to know that your application can keep running.

Something very important to keep in mind is that all of the code you have written runs in the UI thread, but it gets called via a "continuation" by the Task when it completes. Essentially, this is a good replacement for BackgroundWorker for certain scenarios.

The pattern's value

The pattern makes it easier to write asynchronous code, so processes that can take up time no longer jam up the application's UI. In the past, you needed to either home brew something with delegates or Thread, use BackgroundWorker (which was not a pretty pattern), or work with Tasks or lambdas. None of those options addressed the issue of UI updates, which required the BeginInvoke system because you can't modify data in one thread from another. In this pattern, all of your code is running in the UI thread, so you don't have the issues with UI updates. In addition, none of your code is running concurrently, which eliminates the data integrity issues (deadlocks, race conditions) typically associated with concurrency.

Caution: Because all of your code is running on the UI thread, if your async method takes up a lot of time outside of the await-ed call, you lose your benefits pretty quickly. Keep your work in the async method as minimal as possible, and the UI will show no slowdowns.

Summary

If you are doing things that are CPU bound, you should use proper parallel processing; this is not a replacement for that approach. But if you have something that is I/O bound, await is a great way to handle it.

I look forward to getting to work with await in a final form, and I think that it will be a great benefit to .NET developers.

J.Ja

About

Justin James is the Lead Architect for Conigent.

Editor's Picks