I am examining some ASP.NET Web API code that is using .NET 4.7.2.
Here is an example controller and action method:
public class ThingController : System.Web.Http.ApiController
{
// ...
public async Task<IHttpActionResult> GetValue()
{
var value = await _db.GetValue().ConfigureAwait(false);
return Content(value);
}
}
I have read that best practice is to not use ConfigureAwait
in application code so that execution continues with the captured synchronization context, since there may be needed state associated with the captured context. However, in general we should use ConfigureAwait(false)
so that we don't continue on the captured synchronization context unnecessarily.
So my thoughts are that we don't want to be calling ConfigureAwait(false)
anywhere in this Web API code.
Then I read about deadlocks and that it doesn't matter when using ASP.NET Core (although I'm not).
I've added a breakpoint and checked SynchronizationContext.Current
which is null
.
Can I safely remove all calls to ConfigureAwait(false)
from this project? If not, in which cases should these calls remain?
CodePudding user response:
Short answer: The best practice is there for a reason, and you should keep those ConfigureAwait(false)
calls in there at least until you move to ASP.NET Core.
Long answer:
The deadlock problem will manifest if something that calls into your method ends up doing a blocking operation on the task you return (.Result
, or .Wait()
, e.g.), anywhere up the call stack. If you have a high degree of certainty that nobody will break that other best-practice of going "async all the way" then you are probably safe removing those ConfigureAwait calls. But the pain that it causes to try to debug a problem like that can be really frustrating.
There are some tools out there which you could leverage to make life easier. For example, there's a Fody Weaver that can be configured to add ConfigureAwait(false) to all of your awaits as a post-processing step, so your code stays clean but you get the appropriate behavior by default. And I'm sure you can find an analyzer that can be configured to cause a build error when code performs a blocking operation on tasks. https://cezarypiatek.github.io/post/async-analyzers-p1/ might be a good place to start for that.
CodePudding user response:
You should remove ConfigureAwait(false)
invocations from ASP.NET pipeline code. That includes controller action methods.
As it is, if the code after that is using HttpContext.Current
, its value will be null
.