小编典典

为所有服务器端代码调用 ConfigureAwait 的最佳实践

all

当您有服务器端代码(即一些ApiController)并且您的函数是异步的 - 所以它们返回时Task<SomeObject>-
任何时候等待调用的函数是否被认为是最佳实践ConfigureAwait(false)

我读过它的性能更高,因为它不必将线程上下文切换回原始线程上下文。但是,使用 ASP.NET Web
Api,如果您的请求来自一个线程,并且您等待某个函数和调用ConfigureAwait(false),当您返回ApiController函数的最终结果时,可能会将您置于不同的线程。

我在下面输入了一个我正在谈论的示例:

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;
    }
}

阅读 125

收藏
2022-03-04

共1个答案

小编典典

更新: ASP.NET Core
没有SynchronizationContext
. 如果你在 ASP.NET Core
上,用不用都没关系ConfigureAwait(false)

对于 ASP.NET “完整”或“经典”或其他任何内容,此答案的其余部分仍然适用。

原始帖子(针对非核心 ASP.NET):

由 ASP.NET 团队制作的此视频包含有关async在 ASP.NET
上使用的最佳信息。

我读过它的性能更高,因为它不必将线程上下文切换回原始线程上下文。

对于 UI 应用程序也是如此,其中只有一个 UI 线程需要“同步”回。

在 ASP.NET 中,情况要复杂一些。当一个async方法恢复执行时,它会从 ASP.NET 线程池中获取一个线程。如果使用
禁用上下文捕获ConfigureAwait(false),则线程将继续直接执行该方法。如果不禁用上下文捕获,那么线程将重新进入请求上下文,然后继续执行该方法。

所以ConfigureAwait(false)不会为您节省 ASP.NET
中的线程跳转;它确实为您节省了重新输入请求上下文的时间,但这通常非常快。如果您尝试对请求进行少量并行处理,这ConfigureAwait(false)
可能会很有用,但实际上 TPL 更适合大多数情况。

但是,对于 ASP.NET Web Api,如果您的请求来自一个线程,并且您等待某个函数并调用 ConfigureAwait(false),当您返回
ApiController 函数的最终结果时,这可能会将您置于另一个线程.

实际上,只要做一个await可以做到这一点。一旦您的async方法命中await,该 方法 将被阻止但 线程
返回到线程池。当方法准备好继续时,从线程池中抢夺任何线程并用于恢复该方法。

ASP.NET 中唯一的区别ConfigureAwait是该线程在恢复方法时是否进入请求上下文。

2022-03-04