Using ConfigureAwait

By default code after an await continues on the calling thread (i.e. the thread prior to the await keyword). In many cases this is what we want to happen. Remember async methods are not necessarily run on another task/thread, but in those instances where we know that they are truly asynchronous, we might actually want our code after the await to also run in the same context (i.e. on the same background thread of the async method).

So, for the sake of argument we’ll assume we’re awaiting a Task which we know is run on a background thread. Upon completion we intend to process some results from this Task, also on a background thread. Now obviously we could do something like

private async Task Process()
{
   var results = await SomeBackgroundThreadMethod();
   await Task.Run(() => ProcessOnBackgroundThread(results);
}

We can see that if SomeBackgroundThreadMethod runs on a background thread then after the await we continue on the calling thread before again spinning up another Task to run our processing code. So we’re potentially using two background threads when in reality, if we know SomeBackgroundThreadMethod actually is running on a background thread then we could simply continue to process on this same thread.

Okay, so this is a little contrived because, as you know, the SomeBackgroundThreadMethod would itself return a Task and we could simply ContinueWith on this Task. But an alternative to ContinueWith is to call ConfigureAwait on the SomeBackgroundThreadMethod Task, such as

private async Task Process()
{
   var results = await SomeBackgroundThreadMethod().ConfigureAwait(false);
   ProcessOnBackgroundThread(results)
}

Gotchas?

  • Now the code which uses ConfigureAwait seems quite obvious, but ConfigureAwait does not magically create a Task or background thread if none existed on the return from SomeBackgroundThreadMethod. For example if SomeBackgroundThreadMethod simply returns a TaskCompletionSource, ConfigureAwait would simply end up being on the calling thread.
  • ConfigureAwait only affects code following it and within the scope of the method using it, hence in the above code once we exit the Process method all async/await calls will return to their default behaviour, it’s only code within the Process method after the await which continues on the same thread as SomeBackgroundThreadMethod.

References
Task.ConfigureAwait