Mamy tę metodę:
async Task<int> AccessTheWebAsync()
{
HttpClient client = new HttpClient();
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
// You can do work here that doesn't rely on the string from GetStringAsync.
DoIndependentWork();
string urlContents = await getStringTask;
//The thing is that this returns an int to a method that has a return type of Task<int>
return urlContents.Length;
}
Czy niejawna konwersja występuje między Task<int>
a int
? Jeśli nie, to co się dzieje? Jak to działa?
async
słowa kluczowego.Odpowiedzi:
Nie. To tylko część tego, jak
async
/await
działa.Każda metoda zadeklarowana jako
async
musi mieć zwracany typ:void
(unikaj, jeśli to możliwe)Task
(brak wyniku poza powiadomieniem o zakończeniu / niepowodzeniu)Task<T>
(dla logicznego wyniku typuT
w sposób asynchroniczny)Kompilator wykonuje wszystkie odpowiednie opakowania. Chodzi o to, że jesteś asynchronicznie powrocie
urlContents.Length
- nie może sprawić, że metoda po prostu wrócićint
, jak rzeczywista metoda zwróci gdy trafi pierwszyawait
wyraz, który nie został już ukończony. Zamiast tego zwraca wartość,Task<int>
która zakończy się po zakończeniu samej metody asynchronicznej.Zauważ, że
await
robi to odwrotnie - rozpakowuje aTask<T>
doT
wartości, tak jak działa ta linia:... ale oczywiście rozpakowuje je asynchronicznie, podczas gdy samo użycie
Result
spowoduje zablokowanie do zakończenia zadania. (await
może rozpakować inne typy, które implementują oczekiwany wzorzec, aleTask<T>
jest to ten, którego prawdopodobnie będziesz używać najczęściej).To podwójne zawijanie / rozpakowywanie umożliwia komponowanie asynchronii. Na przykład mógłbym napisać inną metodę asynchroniczną, która wywoła Twoją i podwaja wynik:
(Lub po prostu
return await AccessTheWebAsync() * 2;
oczywiście.)źródło
async
/await
i uważam, że jest to wyjątkowo nieintuicyjne. IMO, powinno być słowo kluczowe lub coś podobnego wreturn
celu wyjaśnienia, np.return async result;
(W ten sam sposób, w jakiawait result
„rozpina się”T
zTast<T>
).await
- gdyT foo = someTaskT;
dostaniesz "Nie można niejawnie przekonwertować typuTask<T>
naT
" - w ten sam sposób, w jaki twierdzę, że bardziej sensowne byłoby posiadanie słowa kluczowego dla odwrotności (zawijanieTask<T>
). Jestem za usuwaniem puchu, ale w tym przypadku wydaje mi się, że zapewnia to niepotrzebne zaciemnianieasync
metod. (Oczywiście kwestia jest dyskusyjna, ponieważ uprawnienia, które już zostały wypowiedziane / zakodowane!)async
, myślę, że to wystarczy.Nie wymaga konwersji zadania na int. Po prostu użyj wyniku zadania.
Zwróci wartość, jeśli jest dostępna, w przeciwnym razie zwróci 0.
źródło
Result
; może to spowodować zakleszczenie! Rozważmy na przykład następujący przebieg pracy: (1) Napisz notatkę o treści „skoś trawnik”. (2) Poczekaj, aż trawnik zostanie skoszony (3) Zjedz kanapkę, (4) Zrób wszystko, co jest napisane w notatce. ”Przy takim przepływie pracy nigdy nie jesz kanapki ani nie kosisz trawnika, ponieważ krok 2 to synchroniczne oczekiwanie na temat czegoś, co będziesz robić w przyszłości . Ale to właśnie tutaj opisujesz przepływ pracy.