C# Feature Dossier: Tasks Based Asynchrony with Async and Await

If you haven’t been living under a rock for the past year you’ve at least probably heard about the new C# async and await keywords coming in C# 5 that’s shipping in with Visual Studio 2012. In a nutshell what the feature allows you write asynchronous code and make it look like it’s synchronous. That means that you no longer have to write callback handlers to handle what happens when the async operation you invoked has returned. An illustrative example using good old HttpWebRequest should drive the point:

In this first example we used the traditional Begin/End async pattern on HttpWebRequest to request a website and print it to the console. Notice how you have to split your logic between setting up the request and dealing with the result once results come in. In .net 4 this became a bit easier with the introduction of the Task Parallel Library (TPL) and the Task class.

A way you can think about a Task is that it represents a promise of a future result rather than the actual. In other words sometime in the future I’ll have the value you request. What’s nice about this abstraction is that it allows you to combine asynchronous operations into a single operation thanks to since your returning a promise rather than the actual result.

One thing you might be asking yourself at this point is great I can write an async method in one go now by return a promise of something to come. What if I need to act on the result before I return it to the caller? Glad you asked! And that’s where Task continuations come in. They basically allow you to specify an action to take on a Task once it completes. So enough talk, let’s see this stuff in action:

There are a couple things going on here but take note that unlike with the begin/end async pattern everything is neatly contained within a single method with a Task being returned that will contain the async result being returned.. Let’s break this down starting off with the call to the Task.Factory.FromAsync method. FromAsync is a static method provided by the TPL base class library for bridging the traditional async begin/end pattern over to the new Task based async pattern. The method returns a Task representing the result the begin/end async invocation.

That in and of itself is pretty neat but the real magic of this examples lies in the continuation that’s being defined of the Task we got back from the FromAsync method. All tasks have a method called ContinueWith that then allows you act upon the future result of the Task you call ContinueWith on. Basically, you’re saying what you should do once the parent task or antecedent has completed. No longer do you have to define call backs and event handlers to handle async. You can simple call a method and pass in a delegate. This makes writing async methods immensely easier since your async code is all in one place and reads much better.

The last part is this example is returning the task that was given to us by the call to continue with. This the Task that calling code will wait on for the final result of this asynchronous method. Pretty, nifty right? So now that we’ve seen TPL and Task based asynchrony in action how do C#’s new async and await come into the picture. They make writing and consuming task based async methods so easy that they look like synchronous method calls. No callbacks, no wrapping delegates, events hooks. Just code. (Well it’s all just code in the end but you get my drift).

Seeing is believing so here’s what are method looks like with async and await.

 

Like I said, just code :) The interesting to point here are the introduction on two new keywords. The async keyword in the method signature and the await used in front of the methods that have async at the ends of their names. The async keyword marks a method as being asynchronous and allows the use of the await keyword within it.

The await keyword is the bread and butter of all this. What it does in a nutshell is unwrap a Task by introducing a point of asynchrony into the method at which the compiler can logically pause code flow execution until the Task completes. Point of emphasis here “logically pause” code flow execution. Note I didn’t say block but pause.

One thing to be aware of when writing task based methods with async and await is that the method returns after the first await in the method. Which could or could not be what you want. On WinRT and asp.net the thread is released to do other work and will reschedule itself once the Task that is awaited on completes and continue execution after the await. If you try and await on your main method (in actuality you’ll get compile error, but work with me) in a console app you’ve now released your app’s main thread and the program will terminate. Point of this being while async and await do make async work easier to manage you do still need to be aware of their nature.

Hopefully, this you’ve found this high level overview of async and await at least somewhat helpful. But we’ve only just scratched the surface of what the TPL is capable of. We have yet to talk about CancellationToken that help provide unified cooperative cancellation, scheduling of Tasks with the TaskScheduler, concurrent collection primitives like ConcurrentBag and ConcurrentQueue and many more. One last thing parting gift I’d like to leave you with is that if you’re still on .net 4 you can still leverage the async and await keywords in your app. Since async and await are really just a compiler transform all you really need is the C# 5 compiler in Visual Studio 2012 and the set of supporting types which the C# team has made available to .net 4 developers as Nuget package which you can find here.

×

Comments are closed.