Coder Perfect

For all server-side work, it’s best to use ConfigureAwait.


Is it regarded best practice to use ConfigureAwait(false) every time you await functions when you have server-side code (i.e. some ApiController) and your functions are asynchronous – meaning they return TaskSomeObject>?

I had read that it is more performant since it doesn’t have to switch thread contexts back to the original thread context. However, with ASP.NET Web Api, if your request is coming in on one thread, and you await some function and call ConfigureAwait(false) that could potentially put you on a different thread when you are returning the final result of your ApiController function.

I’ve written an example of what I’m referring about below:

public class CustomerController : ApiController
    public async Task<Customer> Get(int id)
        // you are on a particular thread here
        var customer = await GetCustomerAsync(id).ConfigureAwait(false);

        // now you are on a different thread!  will that cause problems?
        return customer;

Asked by Arash Emami

Solution #1

SynchronizationContext is not available in ASP.NET Core. It makes no difference whether you use ConfigureAwait(false) or not if you’re using ASP.NET Core.

For ASP.NET “Full” or “Classic” or whatever, the rest of this answer still applies.

The original post (for non-Core ASP.NET) was as follows:

The finest information on utilizing async with ASP.NET can be found in this video by the ASP.NET team.

This is especially true in UI apps, since you only have one UI thread to “sync” back to.

The situation is a little more complicated in ASP.NET. When an async method resumes execution, it uses the ASP.NET thread pool to find a thread. When you use ConfigureAwait(false) to deactivate context capture, the thread simply executes the method directly. If the context capture is not disabled, the thread will re-enter the request context before continuing to execute the method.

In ASP.NET, ConfigureAwait(false) does not prevent a thread hop; it does, however, prevent the re-entry of the request context, which is generally quite quick. ConfigureAwait(false) may be handy if you need to execute a modest amount of parallel processing on a request, but TPL is a better fit for the majority of such instances.

Actually, simply performing an await can accomplish this. When an await is encountered in an async method, the method is blocked, but the thread is returned to the thread pool. When the procedure is ready to continue, any thread in the thread pool is stolen and used to restart it.

In ASP.NET, the only distinction is whether the thread enters the request context when the method is resumed.

More background information may be found in my SynchronizationContext MSDN article and my async intro blog post.

Answered by Stephen Cleary

Solution #2

No, to answer your question in a nutshell. At the application level, you shouldn’t call ConfigureAwait(false) like that.

The short version of the long response is as follows: You should always use ConfigureAwait when developing a library when you don’t know your consumer and don’t need a synchronization context (which you shouldn’t in a library, in my opinion) (false). If your library’s consumers consume your asynchronous methods in a blocking approach, they may experience deadlocks. This is dependent on the circumstances.

Here’s a more extensive explanation of the ConfigureAwait method’s importance (a quotation from my blog post):

Also, here are two excellent articles that are relevant to your query:

Finally, Lucian Wischik has a fantastic short film on the subject: Async library methods should consider using Task. ConfigureAwait(false).

Hope this helps.

Answered by tugberk

Solution #3

The most significant disadvantage of using ConfigureAwait(false) is that the thread culture is reset to the system default. If you’ve set up a culture, for example…

    <globalization culture="en-AU" uiCulture="en-AU" />    

If you’re hosting on a server with the en-US culture set, you’ll notice a function named CultureInfo before ConfigureAwait(false). CurrentCulture will restore en-AU, which will be followed by en-US. i.e.

// CultureInfo.CurrentCulture ~ {en-AU}
await xxxx.ConfigureAwait(false);
// CultureInfo.CurrentCulture ~ {en-US}

If your app does anything that requires data to be formatted in a given culture, you’ll need to keep this in mind when using ConfigureAwait (false).

Answered by Mick

Solution #4

I have some general suggestions on how Task should be implemented:

I’ve written a few pieces on the matter, but my recommendation – in addition to Tugberk’s excellent response – is to make all APIs asynchronous and, ideally, to flow the context. Because you’re doing async, you can just use continuations instead of waiting, which means there won’t be any deadlock because the library won’t wait and you’ll keep the flow going, preserving the context (such as HttpContext).

The issue arises when a library provides a synchronous API but implements it using an asynchronous API, necessitating the use of Wait()/Result in your code.

Answered by Aliostad

Post is based on