我正在比较从我的方法中删除await
关键字时的效果,并且它给我的性能提升了15倍以上。
以下方法表现更好:
private static async Task<HttpResponseMessage> AwaitResponse(HttpRequest proxy)
{
foreach (var header in proxy.Request.Headers)
{
Client.Instance.DefaultRequestHeaders.Add(header.Key, header.Value);
}
var response = Client.Instance.SendAsync(proxy.Request).Result;
return response;
}
比这个:
private static async Task<HttpResponseMessage> AwaitResponse(HttpRequest proxy)
{
foreach (var header in proxy.Request.Headers)
{
Client.Instance.DefaultRequestHeaders.Add(header.Key, header.Value);
}
var response = Client.Instance.SendAsync(proxy.Request);
return await response;
}
注意我如何在方法的第一个版本中调用 .Result 。
为什么会这样?为什么会有如此巨大的性能损失?
请注意,Client
只是HttpClient
的静态实例。
答案 0 :(得分:4)
使用await
时,代码的执行上下文将暂停,直到异步方法返回为止。默认情况下,await
会尝试将新线程还原到它所源自的传入同步上下文。这有时会影响性能,因为CLR需要等待原始的SynchronizationContext编组回来。
一般来说,除非您特别需要返回到您离开的相同线程上下文(例如,在客户端应用程序中,返回到UI线程),否则最好添加ConfigureAwait(false)
并继续任意线程。
答案 1 :(得分:4)
鉴于您实际上没有对代码段中的任何内容使用响应,因此无需实际使用async / await或调用.Result
。您只需返回呼叫者的Task
即可等待,或在更高级别呼叫.Result
。
private static Task<HttpResponseMessage> AwaitResponse(HttpRequest proxy) {
foreach (var header in proxy.Request.Headers) {
Client.Instance.DefaultRequestHeaders.Add(header.Key, header.Value);
}
return Client.Instance.SendAsync(proxy.Request);
}
我还建议审核
来自Stephen Cleary的Async/Await - Best Practices in Asynchronous Programming
围绕不混合阻止和异步代码的问题,以及何时以及何时何时ConfigureAwait(false)