C#: Why you should use ConfigureAwait(false) in your library code

Dec 22, 2016 · 3 min read

Writing asynchronous code after the introduction of async/await in .NET4.5 became relatively easy. Async/await keywords improve code readability and programmer productivity as code resembles synchronous code and it's easy to follow, thanks to the compiler taking care of the most difficult part of asynchronous programming.

Let’s create an example to see how easy it is to write async code to curl a specific URL and return its content as a string.

We have our asynchronous call that does not block the calling thread while it fetches the content of Bynder.

In an ideal world people would always use our library in the following way:

However, the programming world is far from ideal and some people might use it in the following way:

This way curl is done in a synchronous way, blocking the calling thread until curl finishes. If this is executed in a Console Application, most of the time our code will run as expected (not necessarily always).

However, if that code is run in a UI Application, for example when a button is clicked like in the following example:

Then the application will freeze and stop working, we have a deadlock. Of course, users of our library will complain because it makes the application unresponsive.

To solve the problem and make our library work in this situation we will have to rewrite our function as follows:

In fact, only adding the first ConfigureAwait(false) would be enough to solve the problem.

In conclusion, it is good practice to always use ConfigureAwait(false) in your library code to prevent unwanted issues.

Now, we will analyse why a deadlock occurs in an UI application (and not in most console applications) and why ConfigureAwait(false) solves this issue.

First we need to understand how most UI applications work:

  • There is one thread that is responsible for the UI: the UI Thread. The UI can only be updated if called from this thread, so if this thread is blocked, the application becomes unresponsive.
  • The UI Thread has a message queue to receive notifications/actions to perform. In Win32 this translates into something like this:

If there is a SynchronizationContext (i.e. we are in the UI thread) the code after an await will run in the original thread context. This is the default and expected behaviour.

If we were to modify a UI component from a thread other than the UI Thread, a ‘System.InvalidOperationException’ would be thrown, like in the following example:

Back to our working example, our async DoCurlAsync call is conceptually equivalent to:

NOTE: this snippet is a simplified version of what actually takes place when using await. It also does not take care of the using keyword for closing resources.

The Post call sends a message to the UI Thread message pump to be processed, so to finish DoCurlAsync it is mandatory that the UI Thread executes await httpResonse.Content.ReadAsStringAsync().

However, in the following scenario:

UI Thread cannot process that instruction because it's blocked. We have a deadlock because DoCurlAsync will never finish. ConfigureAwait(false) configures the task so that continuation after the await does not have to be run in the caller context, therefore avoiding any possible deadlocks.


What's happening with technology at Bynder

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store