Lassen Sie uns zunächst einige Begriffe klären: "asynchron" ( async
) bedeutet, dass der aufrufende Thread möglicherweise vor dem Start wieder kontrolliert wird. In einer async
Methode sind diese "Fließpunkte" await
Ausdrücke.
Dies unterscheidet sich stark von dem Begriff "asynchron", der in der MSDN-Dokumentation seit Jahren (falsch) als "auf einem Hintergrundthread ausgeführt" verwendet wird.
Das Thema weiter zu verwirren, async
ist ganz anders als "erwartbar"; Es gibt einige async
Methoden, deren Rückgabetypen nicht erwartet werden können, und viele Methoden, die erwartete Typen zurückgeben, die nicht erwartet werden async
.
Genug davon, was sie nicht sind ; Hier ist was sie sind :
- Das
async
Schlüsselwort erlaubt eine asynchrone Methode (dh es erlaubt await
Ausdrücke). async
Methoden können zurückgeben Task
, Task<T>
oder (wenn Sie müssen) void
.
- Jeder Typ, der einem bestimmten Muster folgt, kann erwartet werden. Die am häufigsten erwarteten Typen sind
Task
und Task<T>
.
Wenn wir Ihre Frage so umformulieren, dass "Wie kann ich eine Operation für einen Hintergrundthread so ausführen, dass sie erwartet wird", lautet die Antwort Task.Run
:
private Task<int> DoWorkAsync() // No async because the method does not need await
{
return Task.Run(() =>
{
return 1 + 2;
});
}
(Aber dieses Muster ist ein schlechter Ansatz; siehe unten).
Wenn Ihre Frage jedoch lautet: "Wie erstelle ich eine async
Methode, die dem Aufrufer zurückgeben kann, anstatt sie zu blockieren?", Lautet die Antwort, die Methode zu deklarieren async
und await
für ihre "Nachgiebigkeitspunkte" zu verwenden:
private async Task<int> GetWebPageHtmlSizeAsync()
{
var client = new HttpClient();
var html = await client.GetAsync("http://www.example.com/");
return html.Length;
}
Das Grundmuster der Dinge besteht also darin, dass async
Code in seinen await
Ausdrücken von "Wartbaren" abhängt . Diese "Wartezeiten" können andere async
Methoden oder nur reguläre Methoden sein, die Wartezeiten zurückgeben. Reguläre Methoden zurückzukehr Task
/ Task<T>
können verwenden Task.Run
Code auf einem Hintergrund - Thread auszuführen, oder (häufiger) kann sie verwenden , TaskCompletionSource<T>
oder eines ihrer Verknüpfungen ( TaskFactory.FromAsync
, Task.FromResult
usw.). Ich empfehle nicht , eine ganze Methode Task.Run
einzuschließen. Synchrone Methoden sollten synchrone Signaturen haben, und es sollte dem Verbraucher überlassen bleiben, ob sie in Folgendes verpackt werden sollen Task.Run
:
private int DoWork()
{
return 1 + 2;
}
private void MoreSynchronousProcessing()
{
// Execute it directly (synchronously), since we are also a synchronous method.
var result = DoWork();
...
}
private async Task DoVariousThingsFromTheUIThreadAsync()
{
// I have a bunch of async work to do, and I am executed on the UI thread.
var result = await Task.Run(() => DoWork());
...
}
Ich habe ein async
/ await
Intro in meinem Blog. Am Ende stehen einige gute Follow-up-Ressourcen. Auch die MSDN-Dokumente für async
sind ungewöhnlich gut.