当您有服务器端代码(即一些ApiController)并且您的函数是异步的 - 所以它们返回时Task<SomeObject>- 任何时候等待调用的函数是否被认为是最佳实践ConfigureAwait(false)?
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; } }
更新: ASP.NET Core 没有SynchronizationContext. 如果你在 ASP.NET Core 上,用不用都没关系ConfigureAwait(false)。
SynchronizationContext
对于 ASP.NET “完整”或“经典”或其他任何内容,此答案的其余部分仍然适用。
原始帖子(针对非核心 ASP.NET):
由 ASP.NET 团队制作的此视频包含有关async在 ASP.NET 上使用的最佳信息。
async
我读过它的性能更高,因为它不必将线程上下文切换回原始线程上下文。
对于 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,该 方法 将被阻止但 线程 返回到线程池。当方法准备好继续时,从线程池中抢夺任何线程并用于恢复该方法。
await
ASP.NET 中唯一的区别ConfigureAwait是该线程在恢复方法时是否进入请求上下文。
ConfigureAwait