Eu estou comparando o desempenho ao tirar await
palavra-chave do meu método e está me dando um desempenho 15x melhor.
O método a seguir funciona muito melhor:
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;
}
Observe como estou ligando .Resultado na primeira versão do método.
Por que isso está acontecendo? Por que há uma tremenda penalidade no desempenho?
Por favor note que Client
é simplesmente uma instância estática de HttpClient
.
Respostas:
4 para resposta № 1Ao usar await
, o contexto de execução do código é suspenso até que o método assíncrono seja retornado. Por padrão, await
tenta restaurar o novo segmento para ocontexto de sincronização de entrada originado. Isso pode, às vezes, ter implicações de desempenho, já que o CLR precisa aguardar o SynchronizationContext original para retornar.
De um modo geral, a menos que você tenha uma necessidade específica de retornar ao mesmo contexto de encadeamento que você deixou (digamos, em um aplicativo cliente, para retornar ao encadeamento da interface do usuário), é melhor adicioná-lo ConfigureAwait(false)
e continue em qualquer thread arbitrário.
4 para resposta № 2
Dado que você realmente não usa a resposta para nada nos trechos, não há necessidade de usar async / await ou chamar .Result
. Você pode simplesmente devolver o Task
para o chamador aguardar ou ligar .Result
em um nível mais alto.
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);
}
Eu também sugiro rever
Async / Await - Melhores Práticas em Programação Assíncrona de Stephen Cleary
as questões em torno de não misturar o código de bloqueio e assíncrono e também sobre como e quando ConfigureAwait(false)
quando você puder