When you have server-side code (i.e. some ApiController
) and your functions are asynchronous - so they return Task<SomeObject>
- is it considered best practice that any time you await functions that you call ConfigureAwait(false)
?
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 typed up an example of what I am talking about below:
public class CustomerController : ApiController
{
public async Task<Customer> Get(int id)
{
// you are on a particular thread here
var customer = await SomeAsyncFunctionThatGetsCustomer(id).ConfigureAwait(false);
// now you are on a different thread! will that cause problems?
return customer;
}
}
The biggest draw back I've found with using ConfigureAwait(false) is that the thread culture is reverted to the system default. If you've configured a culture e.g ...
and you're hosting on a server whose culture is set to en-US, then you will find before ConfigureAwait(false) is called CultureInfo.CurrentCulture will return en-AU and after you will get en-US. i.e.
If your application is doing anything which requires culture specific formatting of data, then you'll need to be mindful of this when using ConfigureAwait(false).
I have some general thoughts about the implementation of
Task
:using
.ConfigureAwait
was introduced in 4.5.Task
was introduced in 4.0.Task.ContinueWith
they do not b/c it was realised context switch is expensive and it is turned off by default.I have got a few posts on the subject but my take - in addition to Tugberk's nice answer - is that you should turn all APIs asynchronous and ideally flow the context . Since you are doing async, you can simply use continuations instead of waiting so no deadlock will be cause since no wait is done in the library and you keep the flowing so the context is preserved (such as HttpContext).
Problem is when a library exposes a synchronous API but uses another asynchronous API - hence you need to use
Wait()
/Result
in your code.Brief answer to your question: No. You shouldn't call
ConfigureAwait(false)
at the application level like that.TL;DR version of the long answer: If you are writing a library where you don't know your consumer and don't need a synchronization context (which you shouldn't in a library I believe), you should always use
ConfigureAwait(false)
. Otherwise, the consumers of your library may face deadlocks by consuming your asynchronous methods in a blocking fashion. This depends on the situation.Here is a bit more detailed explanation on the importance of
ConfigureAwait
method (a quote from my blog post):Also, here are two great articles for you which are exactly for your question:
Finally, there is a great short video from Lucian Wischik exactly on this topic: Async library methods should consider using Task.ConfigureAwait(false).
Hope this helps.
Update: ASP.NET Core does not have a
SynchronizationContext
. If you are on ASP.NET Core, it does not matter whether you useConfigureAwait(false)
or not.For ASP.NET "Full" or "Classic" or whatever, the rest of this answer still applies.
Original post (for non-Core ASP.NET):
This video by the ASP.NET team has the best information on using
async
on ASP.NET.This is true with UI applications, where there is only one UI thread that you have to "sync" back to.
In ASP.NET, the situation is a bit more complex. When an
async
method resumes execution, it grabs a thread from the ASP.NET thread pool. If you disable the context capture usingConfigureAwait(false)
, then the thread just continues executing the method directly. If you do not disable the context capture, then the thread will re-enter the request context and then continue to execute the method.So
ConfigureAwait(false)
does not save you a thread jump in ASP.NET; it does save you the re-entering of the request context, but this is normally very fast.ConfigureAwait(false)
could be useful if you're trying to do a small amount of parallel processing of a request, but really TPL is a better fit for most of those scenarios.Actually, just doing an
await
can do that. Once yourasync
method hits anawait
, the method is blocked but the thread returns to the thread pool. When the method is ready to continue, any thread is snatched from the thread pool and used to resume the method.The only difference
ConfigureAwait
makes in ASP.NET is whether that thread enters the request context when resuming the method.I have more background information in my MSDN article on
SynchronizationContext
and myasync
intro blog post.