Najpierw wyjaśnijmy trochę terminologii: „asynchroniczny” ( async) oznacza, że może odzyskać kontrolę nad wątkiem wywołującym przed jego uruchomieniem. W asyncmetodzie te punkty „ustępowania” są awaitwyrażeniami.
Jest to bardzo różni się od terminu „asynchroniczny”, ponieważ (błędnie) używany w dokumentacji MSDN od lat oznacza „wykonuje się w wątku w tle”.
Dalsze mylenie problemu asyncjest zupełnie inne niż „oczekiwanie”; istnieją asyncmetody, których typy zwracane są nieoczekiwane, i wiele metod zwracających oczekiwane typy, które nie są oczekiwane async.
Dość o tym, czym nie są ; oto czym one są :
- Słowo
asynckluczowe pozwala na metodę asynchroniczną (tzn. Pozwala na awaitwyrażenia). asyncmetody mogą zwrócić Task, Task<T>lub (jeśli musisz) void.
- Każdy typ zgodny z określonym wzorcem może być oczekiwany. Najczęściej spotykanymi typami są
Taski Task<T>.
Jeśli więc przeformułujemy twoje pytanie na „jak mogę uruchomić operację na wątku w tle w sposób, w jaki jest to oczekiwane”, odpowiedzią jest użycie Task.Run:
private Task<int> DoWorkAsync() // No async because the method does not need await
{
return Task.Run(() =>
{
return 1 + 2;
});
}
(Ale ten wzór jest złym podejściem; patrz poniżej).
Ale jeśli twoje pytanie brzmi: „jak utworzyć asyncmetodę, która może ustępować swojemu programowi wywołującemu zamiast blokować”, odpowiedzią jest zadeklarowanie metody asynci użycie awaitjej punktów „ustępujących”:
private async Task<int> GetWebPageHtmlSizeAsync()
{
var client = new HttpClient();
var html = await client.GetAsync("http://www.example.com/");
return html.Length;
}
Zatem podstawowym wzorem rzeczy jest asynczależność kodu od „oczekiwań” w jego awaitwyrażeniach. Te „oczekiwane” mogą być innymi asyncmetodami lub zwykłymi metodami zwracającymi oczekiwane. Zwykłe metody powracający Task/ Task<T> można użyć Task.Rundo wykonania kodu w wątku tła, lub (częściej) mogą używać TaskCompletionSource<T>lub jeden z jego (skróty TaskFactory.FromAsync, Task.FromResultitp). I nie polecam owijania całą metodę in Task.Run; metody synchroniczne powinny mieć sygnatury synchroniczne i konsument powinien pozostawić pytanie, czy ma być zawinięty w 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());
...
}
Mam async/ awaitintro na moim blogu; na końcu są dobre zasoby uzupełniające. Dokumenty MSDN dla asyncsą również niezwykle dobre.