我可以在 .NET 4.7.2 Web API 中删除 ConfigureAwait(false) 吗?

Can I remove ConfigureAwait(false) in .NET 4.7.2 Web API?

我正在检查一些使用 .NET 4.7.2 的 ASP.NET Web API 代码。

这是一个示例控制器和操作方法:

  public class ThingController : System.Web.Http.ApiController
  {
      // ...

      public async Task<IHttpActionResult> GetValue()
      {
          var value = await _db.GetValue().ConfigureAwait(false);
          return Content(value);
      }
  }

我已阅读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 。但是,通常我们应该使用 ConfigureAwait(false) 这样我们就不会在不必要的情况下继续捕获同步上下文。

所以我的想法是我们不想在这个 Web API 代码的任何地方调用 ConfigureAwait(false)

然后我读到了 deadlocks and that it (虽然我不是)。

我添加了一个断点并检查了 SynchronizationContext.Currentnull

我可以安全地从此项目中删除对 ConfigureAwait(false) 的所有调用吗?如果不是,在什么情况下这些调用应该保留?

您应该从 ASP.NET 管道代码中删除 ConfigureAwait(false) 次调用。这包括控制器操作方法。

照原样,如果后面的代码使用HttpContext.Current,它的值将是null

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.

我想说最好的做法是在库中使用 ConfigureAwait(false),它可以在不同的上下文中使用。对于应用程序代码,ConfigureAwait(false) 通常是不必要的。 (在某些高级情况下,出于性能原因,ConfigureAwait(false) 是必需的,但这种情况很少见)。

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

我同意。除了控制器方法外,我通常在所有可能的地方都使用 ConfigureAwait(false),但是您可以扩展“不要使用 ConfigureAwait(false)”规则以包含 all 应用程序代码。

Then I read about deadlocks...

Deadlocks(如我的博客所述)需要两部分:

  1. 单线程上下文。在 ASP.NET 中,SynchronizationContext 是单线程上下文。
  2. 在那个上下文中阻塞一个线程,等待一些需要那个上下文的代码。这部分通常是由“异步之上的同步”反模式引起的。

在您的代码中,没有异步同步,因此无论是否使用 ConfigureAwait(false) 都不会出现死锁。

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.

实际上,这是非常有问题的。请查看 this article 并确保您已完成在 ASP.NET 上使用 async 代码的所有先决条件。特别是,您必须对 httpRuntime.targetFrameworkaspnet:UseTaskFriendlySynchronizationContext.

进行适当的设置