异步比同步长15倍

时间:2017-07-27 03:55:40

标签: c# asp.net asp.net-web-api async-await dotnet-httpclient

我正在比较从我的方法中删除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的静态实例。

2 个答案:

答案 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)