2

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?

fractor
  • 1,534
  • 2
  • 15
  • 30
  • 1
    I wrote [a lengthy answer about this](https://stackoverflow.com/q/62500130/1202807). Don't use `ConfigureAwait(false)` in application code. Deadlocks only happen when you wait synchronously on async methods, which you shouldn't be doing anyway. – Gabriel Luci Dec 21 '21 at 18:08

2 Answers2

5

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.

I'd say the best practice is to use ConfigureAwait(false) in libraries, which can be used in different contexts. For application code, ConfigureAwait(false) is generally unnecessary. (There are some advanced situations where ConfigureAwait(false) is necessary for performance reasons, but those are rare).

So my thoughts are that we don't want to be calling ConfigureAwait(false) anywhere in this Web API code.

I'd agree. I generally use ConfigureAwait(false) everywhere I can except controller methods, but you can extend the "don't use ConfigureAwait(false)" rule to include all application code.

Then I read about deadlocks...

Deadlocks (as described on my blog) require two parts:

  1. A single-threaded context. In ASP.NET, the SynchronizationContext is a single-threaded context.
  2. Blocking a thread in that context, waiting for some code that needs that context. This part is usually caused by the "sync over async" antipattern.

In your code, there is no sync-over-async, so no possibility of deadlock whether or not ConfigureAwait(false) is used.

I've added a breakpoint and checked SynchronizationContext.Current which is null... HttpContext.Current is null before the call, in fact upon entry to the method.

That is extremely problematic, actually. Please review this article and ensure you have completed all the prerequisites for using async code on ASP.NET. In particular, you must have an appropriate setting for httpRuntime.targetFramework or aspnet:UseTaskFriendlySynchronizationContext.

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
  • Could you explain why I would not want configureAwait(false) on controller methods. What does it matter if it continues on a different thread? ( I am referring to asp net framework as I am aware that the Synchronisation context has been removed from asp net core) – Yossi Sternlicht Aug 01 '22 at 01:14
  • 1
    @JoeStarbright: It just ensures that the context is present when the ASP.NET code resumes executing. I don't know if it's necessary or not; it's not documented either way. I have seen *other* ASP.NET APIs misbehave (hang) without their expected context (also undocumented), so this is just something I choose to do for code defense reasons. – Stephen Cleary Aug 01 '22 at 01:35
0

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.

Paulo Morgado
  • 14,111
  • 3
  • 31
  • 59