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 asyncMethode sind diese "Fließpunkte" awaitAusdrü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, asyncist ganz anders als "erwartbar"; Es gibt einige asyncMethoden, 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
asyncSchlüsselwort erlaubt eine asynchrone Methode (dh es erlaubt awaitAusdrücke). asyncMethoden 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
Taskund 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 asyncMethode, die dem Aufrufer zurückgeben kann, anstatt sie zu blockieren?", Lautet die Antwort, die Methode zu deklarieren asyncund awaitfü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 asyncCode in seinen awaitAusdrücken von "Wartbaren" abhängt . Diese "Wartezeiten" können andere asyncMethoden oder nur reguläre Methoden sein, die Wartezeiten zurückgeben. Reguläre Methoden zurückzukehr Task/ Task<T> können verwenden Task.RunCode auf einem Hintergrund - Thread auszuführen, oder (häufiger) kann sie verwenden , TaskCompletionSource<T>oder eines ihrer Verknüpfungen ( TaskFactory.FromAsync, Task.FromResultusw.). Ich empfehle nicht , eine ganze Methode Task.Runeinzuschließ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/ awaitIntro in meinem Blog. Am Ende stehen einige gute Follow-up-Ressourcen. Auch die MSDN-Dokumente für asyncsind ungewöhnlich gut.