/ / Async toma 15 veces más que sync - c #, asp.net, asp.net-web-api, async-await, dotnet-httpclient

Async tarda 15 veces más que sync: c #, asp.net, asp.net-web-api, async-await, dotnet-httpclient

Estoy comparando el rendimiento al quitar await palabra clave de mi método, y me está dando más de 15 veces mejor rendimiento.

El siguiente método funciona mucho mejor:

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

que este:

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

Note como estoy llamando .Resultado En la primera versión del método.

¿Por qué está pasando esto? ¿Por qué hay una pena de rendimiento tan tremendo?

Tenga en cuenta que Client es simplemente una instancia estática de HttpClient.

Respuestas

4 para la respuesta № 1

Cuando usas await, el contexto de ejecución del código se suspende hasta que se devuelve el método asíncrono. Por defecto, await intenta restaurar el nuevo hilo a lacontexto de sincronización entrante en el que se originó. Esto a veces puede tener implicaciones en el rendimiento, ya que el CLR debe esperar a que el SynchronizationContext original se recupere.

En general, a menos que tenga una necesidad específica de regresar al mismo contexto de hilo que dejó (por ejemplo, en una aplicación cliente, para volver al hilo de la interfaz de usuario), es mejor agregar ConfigureAwait(false) y continuar en cualquier hilo arbitrario.


4 para la respuesta № 2

Dado que en realidad no usa la respuesta para nada en los fragmentos, no hay necesidad de usar async / await o llamar .Result. Usted puede simplemente devolver el Task para que la persona que llama espere o llame .Result en un nivel superior

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

Yo también sugeriría revisar

Async / Await - Mejores Prácticas en Programación Asíncrona de Stephen Cleary

Los problemas en torno a no mezclar el bloqueo y el código asíncrono y también sobre cómo y cuándo ConfigureAwait(false) cuando pueda