/ / Async dauert 15x länger als sync - c #, asp.net, asp.net-web-api, async-await, dotnet-httpclient

Async nimmt 15x länger als sync - c #, asp.net, asp.net-web-api, async-erwarten, dotnet-httpclient

Ich vergleiche die Leistung beim Mitnehmen await Keyword aus meiner Methode, und es gibt mir eine über 15-fach bessere Leistung.

Die folgende Methode funktioniert viel besser:

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

als dieser:

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

Beachten Sie, wie ich anrufe .Ergebnis in der ersten Version der Methode.

Warum passiert dies? Warum gibt es so eine enorme Leistungsstrafe?

Bitte beachte, dass Client ist einfach eine statische Instanz von HttpClient.

Antworten:

4 für die Antwort № 1

Beim Benutzen awaitDer Ausführungskontext des Codes wird angehalten, bis die async-Methode zurückgegeben wird. Standardmäßig, await versucht, den neuen Thread im wiederherzustelleneingehender Synchronisierungskontext, in dem er ursprünglich erstellt wurde. Dies kann manchmal Auswirkungen auf die Leistung haben, da die CLR darauf warten muss, dass der ursprüngliche SynchronizationContext erneut gemarshallt wird.

Im Allgemeinen gilt: Wenn Sie nicht zu demselben Thread-Kontext zurückkehren möchten, den Sie hinterlassen haben (z. B. in einer Client-App, um zum UI-Thread zurückzukehren), ist es am besten, dies hinzuzufügen ConfigureAwait(false) und fahren Sie mit einem beliebigen Thread fort.


4 für die Antwort № 2

Da Sie die Antwort eigentlich nicht für irgendetwas in den Snippets verwenden, müssen Sie nicht tatsächlich async / await verwenden oder anrufen .Result. Sie können das einfach zurückgeben Task für den Anrufer warten oder anrufen .Result auf einer höheren Ebene.

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

Ich würde auch eine Überprüfung vorschlagen

Async / Await - Best Practices in der asynchronen Programmierung von Stephen Cleary

Die Probleme rund um das Mischen von Blocking und asynchronem Code sowie darüber, wie und wann ConfigureAwait(false) wenn du kannst