2012-02-23

Thinking about Async Tasks

In this post, I'm going to clarify how Tasks are used by async/await. This is a little bit different than Tasks as used by the Task Parallel Library, and it's also a little bit different than awaitables as used by async/await.

Tasks Are a Future

A future is some operation that will complete at some future time.

An async Task is not a thread - not even a tiny one. This is one of the most common conceptual hurdles to working with async. Task != Thread.

Similarly, an async Task is not a delegate.

Some tasks do contain a delegate, and they represent some work to be done on a thread. However, as we saw in the Creating Tasks post, tasks created with TaskCompletionSource<T> have no code or delegate at all!

Tasks Complete Once

A task will complete exactly one time. It can complete successfully or with error (cancellation is treated as a special kind of error).

Because tasks complete only once, they're not ideal for representing streams of data or event subscriptions. We'll deal with stream/subscription scenarios in a later post.

Tasks Support Continuations

A continuation is some code that is attached to a task and executed when that task completes. Tasks have direct support for continuations via the ContinueWith method.

However, you usually do not need to call that method. The await keyword will use task continuations to schedule the remainder of the async method as necessary.

Differences between Async Tasks and TPL Tasks

The Task class was introduced with the Task Parallel Library. The TPL usage of Task is a bit more general than the Async usage of Task. Also, the TPL was designed with fork/join parallelism in mind, and those portions of the Task class API are not used with async tasks.

Under the TPL, the creation of a task and the scheduling of that task may be separate. It is possible to create a Task object and not start it until later. Under Async, every task is already in progress; its operation is started when the Task object is created. Because of this, you may have to call Task.Start on a Task returned from TPL code if you want to await it.

TPL has a concept of parent and child tasks. Async tasks do not use this mechanism. There is a logical hierarchy among async tasks, but they do not use the parent/child relationship provided by the TPL.

Each TPL task may have multiple errors. Even if a task only has one exception, it is wrapped in an AggregateException. Async tasks are only expected to have one error, so the await operator will automatically unwrap the single exception if necessary.

Differences between Async Tasks and Awaitables

An awaitable is a very generic form of background operation. Awaitables support testing for completion (IsCompleted), scheduling continuations (OnCompleted), and retrieving the results of the operation (GetResult).

The await operator uses a well-defined pattern, so it's possible to have some very strange awaitables that do work correctly.

For example, the awaitable returned by the Task.Yield method never returns true for IsCompleted, and its OnCompleted will immediately schedule the completions. So, on the one hand it never completes, but on the other hand it is already completed.

WinRT awaitables are also not quite like Task objects. The most important difference is that WinRT operations do not start their operation immediately. Normally, the WinRT awaitable will start the operation for you when it is used in an await expression. However, this won't work as well if you want to have multiple operations running simultaneously. In this case, you can convert any WinRT awaitable into an async Task by calling the StartAsTask extension method.

Functional Concepts

In conclusion, I'd like to point out that we're witnessing more functional concepts gradually enter our imperative language: both future and continuation are concepts borrowed from functional languages.

This helps explain why async code will gently nudge you into a functional programming style. And I'll say it again: this is natural, and should be embraced.

2012-02-16

Reporting Progress from Async Tasks

Today, we'll look at how async methods satisfy a common requirement of background operations: reporting progress.

Progress Reporter Abstraction

When asynchronous methods report progress, they use an abstraction of the "progress reporter" concept: IProgress<in T>. This interface has a single method: void Report(T value). You can't get much simpler than that!

An asynchronous method that wants to report progress just takes an IProgress<T> parameter, with some appropriate type for T. There are two important things to keep in mind:

  1. The parameter can be null. This means that no progress reports are needed.
  2. IProgress<T>.Report is thread-safe, but asynchronous. In other words, you're "posting" the progress reports to the progress reporter. The progress reporter probably hasn't responded to the progress update by the time your method continues.

That second rule can trip people up - it means you can't modify the progress object after it's passed to Report. It is an error to keep a single "current progress" object, update it, and repeatedly pass it to Report.

To avoid this problem, you should create a new progress object each time you call Report. This is easy if your progress type is a value type (the compiler makes a copy of it for you). Alternatively, you could make your progress type immutable and make your own copies.

This is one small step towards a functional mindset. Async/await will gently nudge you away from OOP and towards functional programming. This is natural and should be embraced.

Progress Reporter Implementation

Now let's look at the "receiving" side of progress reports. The caller of the asynchronous method passes in the progress reporter, so it has complete control of how progress reports are handled.

There is one built-in progress reporter: Progress<T>. You can either pass an Action<T> into the constructor or handle the ProgressChanged event.

One important aspect of this class is that it invokes ProgressChanged (and the Action<T>) in the context in which it was constructed. So it's natural to write UI updates:

public async void StartProcessingButton_Click(object sender, EventArgs e)
{
  // The Progress<T> constructor captures our UI context,
  //  so the lambda will be run on the UI thread.
  var progress = new Progress<int>(percent =>
  {
    textBox1.Text = percent + "%";
  });

  // DoProcessing does most of its work on the thread pool.
  await DoProcessingOnThreadPoolAsync(progress);
  textBox1.Text = "Done!";
}

The context keeps the updates nicely synchronized.

However, this doesn't work as well if there's no context to capture. In this case, Progress<T> uses the thread pool context, and you'll have to deal with these problems:

  • Multiple simultaneous updates. Since the event is raised on a thread pool thread, fast updates can cause the same event handlers to run on different thread pool threads at the same time.
  • Updates after completion. If a method issues an update just before it completes, the event may be raised on a thread pool thread after the task has been completed!

You do need to be aware of these problems when using Progress<T> without a UI context. We'll cover more advanced progress composition in a later post, and consider solutions to these problems.

Progress Report Exceptions

Progress<T> raises its event within a captured context. However, this event is not wrapped in a Task or anything like that; it is just executed directly. This means that any exceptions from that event's handlers will propagate directly to the context.

In other words, exceptions from Progress<T>.ProgressChanged are treated just like exceptions from other event handlers.

In other words, don't throw exceptions from Progress<T>.ProgressChanged. :)

More Progress Reporter Implementations!

The callback-based Progress<T> is great for general use, but there's no reason you couldn't write your own IProgress<T> that works better with your own code base. Here are some implementations from the AsyncEx library:

  • PropertyProgress<T> has a property called Progress and implements INotifyPropertyChanged, so progress updates can update data bindings. This implementation also captures its context just like Progress<T>, which is expected for data binding updates.
  • ObserverProgress<T> forwards progress updates to an IObserver<T>, where they can be composed using Rx.
  • ProducerProgress<T> and DataflowProgress<T> both place progress updates into containers (an IProducerConsumerCollection<T> or an ITargetBlock<TInput>, respectively).

Defining "Progress"

We've covered a lot about progress reporting without actually saying much about the progress update itself (other than it must be passed by value - so either a value type, or an immutable reference type works best).

The information in this section is not Gospel. It's just a tip from my own (limited) experience dealing with progress updates from async methods. YMMV.

It's natural to think of a progress report as cumulative - the canonical example being "percent complete." However, I recommend a different approach: have incremental progress reports for all reusable code and only convert it to cumulative just before it is displayed to the user.

So an FTP file downloader would report the number of bytes transferred after each write to disk, not the entire number of bytes transferred so far:

public async Task DownloadFileAsync(string fileName, IProgress<int> progress)
{
  using (var fileStream = ...) // Open local file for writing
  using (var ftpStream = ...) // Open FTP stream
  {
    while (true)
    {
      var bytesRead = await ftpStream.ReadAsync(...);
      if (bytesRead == 0)
        return;
      await fileStream.WriteAsync(...);
      if (progress != null)
        progress.Report(bytesRead);
    }
  }
}

Perhaps it's just me, but I find it easier to compose incremental updates like this rather than cumulative ones.

2012-02-09

Creating Tasks

Microsoft will give us lots of awaitables in .NET 4.5, but there are some situations where we want to create our own awaitable. Task<T> and Task are the easiest awaitable types to work with in .NET, so today we'll look at different ways awaitable Task objects can be constructed.

All Task objects fall into one of two types: "code" and "event". Code-based tasks have a delegate that they are trying to run. Event-based tasks have no code; they're just waiting for some event to take place.

Tasks as Events

Tasks without code can represent any kind of event. The most common examples are I/O completion events, but event-based tasks can actually wrap any kind of event.

To create an event-based task, use the TaskCompletionSource<TResult> class:

public static Task<int> MyIntegerEventAsync()
{
  TaskCompletionSource<int> tcs = new TaskCompletionSource<int>();

  // Register for the "event".
  //   For example, if this is an I/O operation, start the I/O and register for its completion.

  // When the event fires, it should call:
  //   tcs.TrySetResult(...); // For a successful event.
  // or
  //   tcs.TrySetException(...); // For some error.
  // or
  //   tcs.TrySetCanceled(); // If the event was canceled.

  // ThreadCompletionSource is thread-safe, so you can call these methods from whatever thread you want.

  // Return the Task<int>, which will complete when the event triggers.
  return tcs.Task;
}

Remember that Task<T> and Task are awaitable, so you can await the result of MyIntegerEventAsync even though it's not an async method.

You probably won't have to use TaskCompletionSource<TResult> directly; you can use TaskFactory.FromAsync to wrap any operation that uses IAsyncResult (and most existing asynchronous I/O methods do use IAsyncResult). Internally, FromAsync does use TaskCompletionSource<TResult>.

Nito.AsyncEx includes an AsyncFactory type which works like TaskFactory.FromAsync but is slightly easier to use and supports more arguments. It also includes a (non-generic) TaskCompletionSource, which is easier to use when creating (non-generic) Tasks.

Tasks as Code

Remember (from our async intro post) that the async keyword does not run the method on a background thread. However, you can use Task.Run to run code on a background thread:

public static void MyThreadPoolMethod()
{
  // Do work (assuming we're running on the thread pool).
}

public async Task DoStuffAsync()
{
  var cpuResult = await Task.Run(MyThreadPoolMethod);

  // Use cpuResult...
}

Task.Run will take a delegate and run it on the thread pool for you. It wraps the delegate into a Task<T> or Task, and the Task wrapper takes care of all the error handling and other stuff correctly.

What about other threads? What if you don't want to run your code on the thread pool?

If you have a particular context in which you want to run your code, you can use a TaskFactory initialized with a TaskScheduler that targets your context. You can then call TaskFactory.StartNew to run your code in that context. In fact, Task.Run is just a shorthand for Task.Factory.StartNew.

It's possible to capture the current synchronization context into a TaskScheduler by calling TaskScheduler.FromCurrentSynchronizationContext, and then use it later (e.g., from a background thread) to run code within that context. Normally there are better ways to do this, but it is an option.

Before async/await, this was a good way to send progress reports from a background task to the UI. With async/await, there is now a better way.

Writing your own TaskScheduler is possible, but frustrating due to the lack of MSDN documentation. Fortunately, it's almost never necessary.

If you need a specific thread (e.g., an STA thread) that supports TaskScheduler, you can use the AsyncContextThread type in the Nito.AsyncEx library.

There are some pretty cool tricks we can pull off using the built-in TaskScheduler/TaskFactory types. We'll look at more advanced TaskScheduler situations in later posts.

Tasks as Async Methods

This is a special case of code-based Tasks - and it's easy to overlook!

The flat-out easiest way to create Task objects is to write an asynchronous method:

public async Task<int> DivideAsync(int numerator, int denominator)
{
  await Task.Delay(100);
  return numerator / denominator;
}

We do not create a Task<int> in our code, but the compiler rewrites our code so that a Task<int> is created and returned. When the method completes, the task completes.

That's the easiest way to create Task objects! However, it only works if you're building on existing awaitables; if you aren't in this situation, then you should use TaskFactory.StartNew or TaskCompletionSource<TResult>.

2012-02-07

Async Unit Tests, Part 2: The Right Way

Last time, we looked at incorrect approaches to async unit testing. We also identified the underlying problem: that unit tests do not have an appropriate async context.

At this point, the solution should be pretty obvious: give the unit tests an async context!

It really is that easy! Why, all you have to do is write your own SynchronizationContext implementation. Keep in mind that thread-safety is paramount, because the methods under test may interact with the thread pool or other async contexts. Note that async void methods interact with SynchronizationContext in a different way than other async methods. Oh, and also remember that exceptions need special handling in some cases so their original call stack is preserved appropriately, and if you're on VS2010 you'll need to hack this in because there's no support for it on .NET 4.0.

Just kidding! Ha, ha! The good folks on the Async team have done all the hard work for you. :)

Right Way #1: The Official Approach

If you have the Async CTP installed, then check out the "My Documents\Microsoft Visual Studio Async CTP\Samples\(C# Testing) Unit Testing\AsyncTestUtilities" folder. You'll find not just one, but three async-compatible contexts, ready for you to use!

You should use GeneralThreadAffineContext unless you absolutely need another one. To use it, just copy AsyncTestUtilities.cs, CaptureAndRestorer.cs, and GeneralThreadAffineContext.cs into your test project.

Then, take each unit test and re-write it so that it has a context:

[TestMethod]
public void FourDividedByTwoIsTwo()
{
  GeneralThreadAffineContext.Run(async () =>
  {
    int result = await MyClass.Divide(4, 2);
    Assert.AreEqual(2, result);
  });
}

[TestMethod]
[ExpectedException(typeof(DivideByZeroException))]
public void DenominatorIsZeroThrowsDivideByZero()
{
  GeneralThreadAffineContext.Run(async () =>
  {
    await MyClass.Divide(4, 0);
  });
}

Our unit test methods are not async. Each one sets up an async context and passes the actual test into it as an async lambda expression. So, the actual test code can still be written with all the benefits of async/await, and the async context takes care of making sure it runs as expected:

Just as importantly, the async context ensures that tests that should fail, will fail:

[TestMethod]
public void FourDividedByTwoIsThirteen_ShouldFail()
{
  GeneralThreadAffineContext.Run(async () =>
  {
    int result = await MyClass.Divide(4, 2);
    Assert.AreEqual(13, result);
  });
}

And everyone lived happily ever after!

Well, sort of. This solution does work, but it's a bit cumbersome. Copying code files into each test project? Modifying every unit test to set up its own async context? Really?

Right Way #2: Now with Less Effort!

Boy, if only there was some way to have the MSTest framework apply the async context for us, then we could just write async unit test methods and not worry about it!

Oh yeah - there is. Visual Studio allows you to define a custom "test type." It really is that easy! Why, all you have to do is... ah, forget it. A custom "async unit test" type is already available:

Sweet.

Now you can write async unit tests the obvious way:

[TestMethod]
public async void FourDividedByTwoIsTwoAsync()
{
  int result = await MyClass.Divide(4, 2);
  Assert.AreEqual(2, result);
}

[TestMethod]
[ExpectedException(typeof(DivideByZeroException))]
public async void DenominatorIsZeroThrowsDivideByZeroAsync()
{
  await MyClass.Divide(4, 0);
}

And it works:

And test failures written the obvious way actually fail:

[TestMethod]
public async void FourDividedByTwoIsThirteenAsync_ShouldFail()
{
  int result = await MyClass.Divide(4, 2);
  Assert.AreEqual(13, result);
}

Sniff... It's... so... beautiful...

But not quite perfect. You still have to add a NuGet package and remember to change [TestClass] to [AsyncTestClass].

Tip: You can download an Async Unit Test item type which uses [AsyncTestClass] instead of [TestClass]. This makes writing new async tests just a little bit easier, but not entirely foolproof.

Future Directions

xUnit.NET has recently released first-class support for asynchronous unit tests: in version 1.9 (2012-01-02) and newer, for any test method returning Task/Task<T>, the test framework will wait until the task completes before declaring success/failure. However, as of now, it does not support async void unit tests; this is planned for a future release.

I've been in contact with some people inside of Microsoft regarding this issue, and they said they're aware of it and are considering various options. They wouldn't give me any details, of course, but they did suggest that I would be "pleasantly surprised" when Visual Studio vNext comes out.

So, that's where we are today. Hopefully Microsoft will ship built-in async unit test support in Visual Studio vNext, and I'll be able to look back at this blog post and laugh at how fraught with peril async unit testing used to be.

2012-02-06

Async Unit Tests, Part 1: The Wrong Way

"Code without tests does not exist."

(Overheard at CodeMash)

The core meaning of this quote is that code without unit tests is not as useful as code with unit tests. The speaker even goes so far as to say he won't use code without tests.

I don't take a position quite this extreme, but I definitely agree with the underlying sentiment: that code with unit tests is far more useful. Unit tests prove correct functionality (at least for a limited set of cases). Unit tests also provide a sort of documentation.

If you don't write unit tests - or if you or your manager think writing tests just delays software development - then I refer you to the best computer book ever written, Code Complete. In that book, Steve McConnell presents some very interesting hard facts about testing.

I hope we can all agree that unit testing is a fundamental skill in Modern Programming. And this brings me to a sad chapter in async/await support: the "obvious" way to do unit tests is wrong.

Let's start with a simple asynchronous method. So simple, in fact, that it will just pretend to work for a while and then do a single integer division:

public static class MyClass
{
  public static async Task<int> Divide(int numerator, int denominator)
  {
    // Work for a while...
    await Task.Delay(10); // (Use TaskEx.Delay on VS2010)

    // Return the result
    return numerator / denominator;
  }
}

Boy, it doesn't seem that there can be much wrong with that code! But as we'll see, there's a lot that can be wrong with the unit tests...

When developers write unit tests for async code, they usually take one of two mistaken approaches (with the second one being what I call "obvious"). We'll look at each of these approaches in this post and examine why they're wrong, and look at solutions next time.

Wrong Way #1: Using Task.Wait and Task.Result

This mistake is most common for people new to async: they decide to wait for the task to complete and then check its result. Well, that seems logical enough, and some unit tests written this way actually work:

[TestMethod]
public void FourDividedByTwoIsTwo()
{
  Task<int> task = MyClass.Divide(4, 2);
  task.Wait();
  Assert.AreEqual(2, task.Result);
}

But one of the problems with this approach is unit tests that check error handling:

[TestMethod]
[ExpectedException(typeof(DivideByZeroException))]
public void DenominatorIsZeroThrowsDivideByZero()
{
  Task<int> task = MyClass.Divide(4, 0);
  task.Wait();
}

This unit test is failing, even though the async method under test is throwing a DivideByZeroException. The Test Results Details explains why:

The Task class is wrapping our exception into an AggregateException. This is why the Task.Wait and Task.Result members should not be used with new async code (see the end of last week's async intro post).

Well, we could await the task, which would unwrap the exception for us. This would require our test method to be async. Congratulations, you can move on to the next section.

Wrong Way #2: Using Async Test Methods

This mistake is more common for people who have used async in some real-world code. They've observed how async "grows" through the code base, and so it's natural to extend async to the test methods. This is what I consider the "obvious" solution:

[TestMethod]
public async void FourDividedByTwoIsTwoAsync()
{
  int result = await MyClass.Divide(4, 2);
  Assert.AreEqual(2, result);
}

Yay! It works!

...

Wait...

[TestMethod]
public async void FourDividedByTwoIsThirteenAsync()
{
  int result = await MyClass.Divide(4, 2);
  Assert.AreEqual(13, result);
}

Um, that test should certainly not be passing! What is going on here???

We've encountered a situation very similar to async in Console programs: there is no async context provided for unit tests, so they're just using the thread pool context. This means that when we await our method under test, then our async test method returns to its caller (the unit test framework), and the remainder of the async test method - including the Assert - is scheduled to run on the thread pool. When the unit test framework sees the test method return (without an exception), then it marks the method as "Passed". Eventually, the Assert will fail on the thread pool.

There is now a race condition. There's no race condition in the test itself; it will always pass (incorrectly). The race condition is when the assertion fires. If the assertion fires after the unit test framework finishes the test run, then you'll see a successful test run (like the last screenshot). But if the assertion fires before the unit test framework finishes the test run, then you'll see something like this:

Clicking on the link shows that the Assertion is indeed failing on the thread pool, some time after the test is considered completed and "Passed":

Next Time: The Right Way

During CodeMash, I gave a lightning talk about async unit testing. You could almost hear the teeth grinding at this point, when the TDD/BDD fans discovered that async unit tests were essentially broken. But do not give up hope!

Tomorrow we'll look at the right way to do async unit testing. In fact, we'll look at two right ways: the "official" way, and a brand-new way that's even better!

2012-02-03

Async Console Programs

Once you start using asynchronous code, it kind of "grows" through your codebase. It's easier for asynchronous code to work with other asynchronous code, so it's natural to start making everything asynchronous.

If you're writing a console program, you may end up wanting an asynchronous main method, like this:

class Program
{
  static async void Main(string[] args)
  {
    ...
  }
}

Unfortunately, that doesn't work (and in fact, the Visual Studio 11 compiler will reject an async Main method). Remember from our intro post that an async method will return to its caller before it is complete. This works perfectly in UI applications (the method just returns to the UI event loop) and ASP.NET applications (the method returns off the thread but keeps the request alive). It doesn't work out so well for Console programs: Main returns to the OS - so your program exits.

You can work around this by providing your own async-compatible context. AsyncContext is a general-purpose context that can be used to enable an asynchronous MainAsync:

class Program
{
  static void Main(string[] args)
  {
    AsyncContext.Run(() => MainAsync(args));
  }

  static async void MainAsync(string[] args)
  {
    ...
  }
}

Update (2012-02-16): AsyncContext will propagate exceptions, and the RunTask method can handle tasks with return values. So a more realistic console example would be:

class Program
{
  static int Main(string[] args)
  {
    try
    {
      return AsyncContext.RunTask(() => MainAsync(args)).Result;
    }
    catch (Exception ex)
    {
      Console.Error.WriteLine(ex);
      return -1;
    }
  }

  static async Task<int> MainAsync(string[] args)
  {
    ...
  }
}

Note: normally, you do not want to call Task.Result in async/await code; you want to await the task instead. The example above is an exception to this rule: RunTask will propagate the task exceptions, so any task returned from RunTask completed successfully, so it's safe to call Result.

That's all for today; next week we'll start looking at asynchronous unit tests, which suffer from a similar problem.

2012-02-02

Async and Await

Most people have already heard about the new "async" and "await" functionality coming in Visual Studio 11. This is Yet Another Introductory Post.

First, the punchline: Async will fundamentally change the way most code is written.

Yup, I believe async/await will have a bigger impact than LINQ. Understanding async will be a basic necessity just a few short years from now.

Introducing the Keywords

Let's dive right in. I'll use some concepts that I'll expound on later on - just hold on for this first part.

Asynchronous methods look something like this:

public async Task DoSomethingAsync()
{
  // In the Real World, we would actually do something...
  // For this example, we're just going to (asynchronously) wait 100ms.
  await Task.Delay(100);
}

The "async" keyword enables the "await" keyword in that method. That's all the async keyword does! It does not run this method on a thread pool thread, or do any other kind of magic. The async keyword only enables the await keyword.

The beginning of an async method is executed just like any other method. That is, it runs synchronously until it hits an "await" (or throws an exception).

The "await" keyword is where things can get asynchronous. Await is like a unary operator: it takes a single argument, an awaitable (an "awaitable" is an asynchronous operation). Await examines that awaitable to see if it has already completed; if the awaitable has already completed, then the method just continues running (synchronously, just like a regular method).

If "await" sees that the awaitable has not completed, then it acts asynchronously. It tells the awaitable to run the remainder of the method when it completes, and then returns from the async method. Await will also capture the current context when it passes the remainder of the method to the awaitable.

Later on, when the awaitable completes, it will execute the remainder of the async method (within the captured context).

I like to think of "await" as an "asynchronous wait". That is to say, the async method pauses until the awaitable is complete (so it waits), but the actual thread is not blocked (so it's asynchronous).

Awaitables

As I mentioned, "await" takes a single argument - an "awaitable" - which is an asynchronous operation. There are two awaitable types already common in the .NET framework: Task<T> and Task.

There are also other awaitable types: special methods such as "Task.Yield" return awaitables that are not Tasks, and the WinRT runtime (coming in Windows 8) has an unmanaged awaitable type. You can also create your own awaitable (usually for performance reasons), or use extension methods to make a non-awaitable type awaitable.

That's all I'm going to say about making your own awaitables. In the entire time I've used async/await, I've never had to write my own awaitable. If you want to know more about writing your own awaitables, see the Parallel Team Blog or Jon Skeet's Blog.

One important point about awaitables is this: it is the type that is awaitable, not the method returning the type. In other words, you can await the result of an async method that returns Task ... because the method returns Task, not because it's async. So you can also await the result of a non-async method that returns Task:

public async Task NewStuffAsync()
{
  // Use await and have fun with the new stuff.
  await ...
}

public Task MyOldTaskParallelLibraryCode()
{
  // Note that this is not an async method, so we can't use await in here.
  ...
}

public async Task ComposeAsync()
{
  // We can await Tasks, regardless of where they come from.
  await NewStuffAsync();
  await MyOldTaskParallelLibraryCode();
}
Tip: If you have a very simple asynchronous method, you may be able to write it without using the await keyword (e.g., using Task.FromResult). If you can write it without await, then you should write it without await, and remove the async keyword from the method. A non-async method returning Task.FromResult is more efficient than an async method returning a value.

Return Types

Async methods can return Task<T>, Task, or void. In almost all cases, you want to return Task<T> or Task, and return void only when you have to.

Why return Task<T> or Task? Because they're awaitable, and void is not. So if you have an async method returning Task<T> or Task, then you can pass the result to await. With a void method, you don't have anything to pass to await.

You have to return void when you have async event handlers.

You can also use async void for other "top-level" kinds of actions - e.g., a single "static async void MainAsync()" for Console programs or "async void TestMethod()" for unit tests. However, these uses of async void have their own problems; see Async Console Programs and Async Unit Testing. The primary use case for async void methods is event handlers.

Returning Values

Async methods returning Task or void do not have a return value. Async methods returning Task<T> must return a value of type T:

public async Task<int> CalculateAnswer()
{
  await Task.Delay(100); // (Probably should be longer...)

  // Return a type of "int", not "Task<int>"
  return 42;
}

This is a bit odd to get used to, but there are good reasons behind this design.

Context

In the overview, I mentioned that when await decides to act asynchronously, it captures the current "context" and then applies it to the remainder of the async method. What exactly is that "context"?

Simple answer:

  1. If you're on a UI thread, then it's a UI context.
  2. If you're responding to an ASP.NET request, then it's an ASP.NET request context.
  3. Otherwise, it's usually a thread pool context.

Complex answer:

  1. If SynchronizationContext.Current is not null, then it's the current SynchronizationContext. (UI and ASP.NET request contexts are SynchronizationContext contexts).
  2. Otherwise, it's the current TaskScheduler (TaskScheduler.Default is the thread pool context).

What does this mean in the real world? For one thing, capturing (and restoring) the UI/ASP.NET context is done transparently:

// WinForms example (it works exactly the same for WPF).
private async void DownloadFileButton_Click(object sender, EventArgs e)
{
  // Since we asynchronously wait, the UI thread is not blocked by the file download.
  await DownloadFileAsync(fileNameTextBox.Text);

  // Since we resume on the UI context, we can directly access UI elements.
  resultTextBox.Text = "File downloaded!";
}

// ASP.NET example
protected async void Page_Load(object sender, EventArgs e)
{
  // Since we asynchronously wait, the ASP.NET thread is not blocked by the file download.
  // This allows the thread to handle other requests while we're waiting.
  await DownloadFileAsync(...);

  // Since we resume on the ASP.NET context, we can access the current request.
  // We may actually be on another *thread*, but we have the same ASP.NET request context.
  Response.Write("File downloaded!");
}

This is great for event handlers, but it turns out to not be what you want for most other code (which is, really, most of the async code you'll be writing).

Avoiding Context

Most of the time, you don't need to sync back to the "main" context. Most async methods will be designed with composition in mind: they await other operations, and each one represents an asynchronous operation itself (which can be composed by others). In this case, you want to tell await to not capture the current context by calling ConfigureAwait and passing false, e.g.:

private async Task DownloadFileAsync(string fileName)
{
  // Use HttpClient or whatever to download the file contents.
  var fileContents = await DownloadFileContentsAsync(fileName).ConfigureAwait(false);

  // Note that because of the ConfigureAwait(false), we are not on the original context here.
  // Instead, we're running on the thread pool.

  // Write the file contents out to a disk file.
  await WriteToDiskAsync(fileName, fileContents).ConfigureAwait(false);

  // The second call to ConfigureAwait(false) is not *required*, but it is Good Practice.
}

// WinForms example (it works exactly the same for WPF).
private async void DownloadFileButton_Click(object sender, EventArgs e)
{
  // Since we asynchronously wait, the UI thread is not blocked by the file download.
  await DownloadFileAsync(fileNameTextBox.Text);

  // Since we resume on the UI context, we can directly access UI elements.
  resultTextBox.Text = "File downloaded!";
}

The important thing to note with this example is that each "level" of async method calls has its own context. DownloadFileButton_Click started in the UI context, and called DownloadFileAsync. DownloadFileAsync also started in the UI context, but then stepped out of its context by calling ConfigureAwait(false). The rest of DownloadFileAsync runs in the thread pool context. However, when DownloadFileAsync completes and DownloadFileButton_Click resumes, it does resume in the UI context.

A good rule of thumb is to use ConfigureAwait(false) unless you know you do need the context.

Async Composition

So far, we've only considered serial composition: an async method waits for one operation at a time. It's also possible to start several operations and await for one (or all) of them to complete. You can do this by starting the operations but not awaiting them until later:

public async Task DoOperationsInParallelAsync()
{
  Task[] tasks = new Task[3];
  tasks[0] = DoOperation0();
  tasks[1] = DoOperation1();
  tasks[2] = DoOperation2();

  // At this point, all three tasks are running in parallel.

  // Now, we await them all.
  await Task.WhenAll(tasks);
}

public async Task<int> GetFirstToRespondAsync()
{
  // Call two web services; take the first response.
  Task<int>[] tasks = new[] { WebService1(), WebService2() };

  // Await for the first one to respond.
  Task<int> firstTask = await Task.WhenAny(tasks);

  // Return the result.
  return await firstTask;
}

By using parallel composition (Task.WhenAll or Task.WhenAny), you can perform simple parallel operations. However, this is not a substitute for the Task Parallel Library - any advanced CPU-intensive parallel operations should probably be done with the TPL.

Guidelines

Read the Task-based Asynchronous Pattern (TAP) document. It is extremely well-written, and includes guidance on API design and the proper use of async/await (including cancellation and progress reporting).

There are many new await-friendly techniques that should be used instead of the old blocking techniques. If you have any of these Old examples in your new async code, you're Doing It Wrong(TM):

OldNewDescription
task.Waitawait taskWait/await for a task to complete
task.Resultawait taskGet the result of a completed task
Task.WaitAnyawait Task.WhenAnyWait/await for one of a collection of tasks to complete
Task.WaitAllawait Task.WhenAllWait/await for every one of a collection of tasks to complete
Thread.Sleepawait Task.DelayWait/await for a period of time
Task constructorTask.Run or TaskFactory.StartNewCreate a code-based task