Dla najszybszej nauki ..
Zrozumienie przebiegu wykonywania metody (z diagramem): 3 minuty
Pytanie introspekcja (nauka): 1 min
Szybko przejdź przez składnię cukru: 5 minut
Podziel się zamieszaniem programisty: 5 minut
Problem: Szybka zmiana rzeczywistej implementacji normalnego kodu na kod asynchroniczny: 2 minuty
Gdzie teraz?
Zrozumienie przebiegu wykonywania metody (z diagramem): 3 minuty
Na tym obrazie skup się na # 6 (nic więcej)
W kroku # 6: Wykonanie zatrzymało się tutaj, ponieważ zabrakło pracy. Aby kontynuować, potrzebuje wyniku z getStringTask (rodzaj funkcji). Dlatego używa await
operatora, aby zawiesić postęp i oddać kontrolę (wydajność) wzywającemu (tej metody jesteśmy). Rzeczywiste wywołanie getStringTask zostało wykonane wcześniej w punkcie 2. Na nr 2 złożono obietnicę zwrócenia wyniku łańcucha.Ale kiedy zwróci wynik? Czy powinniśmy (# 1: AccessTheWebAsync) ponownie wykonać drugie połączenie? Kto otrzyma wynik, # 2 (komunikat wywołujący) lub # 6 (czekający komunikat)
Zewnętrzny obiekt wywołujący AccessTheWebAsync () również czeka teraz. Więc osoba dzwoniąca czeka na AccessTheWebAsync, a AccessTheWebAsync w tej chwili czeka na GetStringAsync. Interesującą rzeczą jest AccessTheWebAsync wykonał trochę pracy przed czekaniem (# 4), być może, aby zaoszczędzić czas na czekaniu. Ta sama swoboda wielozadaniowości jest również dostępna dla zewnętrznego rozmówcy (i wszystkich dzwoniących w łańcuchu) i jest to największy plus tego „asynchronicznego” rozwiązania! Wydaje Ci się, że jest synchroniczny ... lub normalny, ale tak nie jest.
Pamiętaj, że metoda została już zwrócona (# 2), nie może powrócić ponownie (nie drugi raz). Więc skąd dzwoniący będzie wiedział? Chodzi przede wszystkim o zadania! Zadanie zostało przekazane. Zadanie było oczekiwane (nie metoda, nie wartość). Wartość zostanie ustawiona w zadaniu. Status zadania zostanie ustawiony na zakończenie. Dzwoniący monitoruje tylko Zadanie (# 6). Więc 6 # jest odpowiedzią na pytanie, gdzie / kto uzyska wynik. Dalsze informacje na później tutaj .
Pytanie introspekcja ze względu na naukę: 1 min
Dostosujmy nieco pytanie:
Jak i kiedy używać i ? async
await
Tasks
Ponieważ nauka Task
automatycznie obejmuje pozostałe dwa (i odpowiada na twoje pytanie)
Szybko przejdź przez składnię cukru: 5 minut
Przed konwersją (metoda oryginalna)
internal static int Method(int arg0, int arg1)
{
int result = arg0 + arg1;
IO(); // Do some long running IO.
return result;
}
Metoda zadaniowa do wywołania powyższej metody
internal static Task<int> MethodTask(int arg0, int arg1)
{
Task<int> task = new Task<int>(() => Method(arg0, arg1));
task.Start(); // Hot task (started task) should always be returned.
return task;
}
Czy wspominaliśmy o oczekiwaniu lub asynchronizacji? Nie. Wywołaj powyższą metodę, a otrzymasz zadanie, które możesz monitorować. Wiesz już, co zwraca zadanie .. liczba całkowita.
Wywołanie zadania jest nieco trudne i wtedy zaczynają się pojawiać słowa kluczowe. Nazwijmy MethodTask ()
internal static async Task<int> MethodAsync(int arg0, int arg1)
{
int result = await HelperMethods.MethodTask(arg0, arg1);
return result;
}
Ten sam kod powyżej dodany jako obraz poniżej:
- „Czekamy” na zakończenie zadania. Stąd
await
- Ponieważ używamy funkcji czekaj, musimy użyć
async
(obowiązkowa składnia)
- MethodAsync z
Async
prefiksem (standard kodowania)
await
jest łatwy do zrozumienia, ale pozostałe dwa ( async
, Async
) mogą nie być :). Cóż, należy zrobić dużo więcej sensu kompilatora though.Further czyta na później tutaj
Więc są 2 części.
- Utwórz „Zadanie”
- Utwórz cukier składniowy, aby wywołać zadanie (
await+async
)
Pamiętaj, że mieliśmy zewnętrzny program wywołujący AccessTheWebAsync () i ten program wywołujący również nie jest oszczędzony ... tzn. Potrzebuje tego samego await+async
. I łańcuch trwa. Ale zawsze będzie Task
jeden koniec.
Wszystko w porządku, ale jeden programista był zaskoczony, widząc brak # 1 (Zadanie) ...
Podziel się zamieszaniem programisty: 5 minut
Deweloper popełnił błąd, nie wdrażając, Task
ale nadal działa! Spróbuj zrozumieć pytanie i tylko zaakceptowaną odpowiedź podaną tutaj . Mam nadzieję, że przeczytałeś i w pełni zrozumiałeś. Podsumowując, możemy nie zobaczyć / zaimplementować „Zadania”, ale jest ono zaimplementowane gdzieś w klasie nadrzędnej. Podobnie w naszym przykładzie wywołanie już zbudowanej MethodAsync()
jest znacznie łatwiejsze niż implementacja tej metody za pomocą Task
( MethodTask()
) samego siebie. Większość programistów ma problemy z przekonaniem się Tasks
podczas konwersji kodu na kod asynchroniczny.
Wskazówka: spróbuj znaleźć istniejącą implementację Async (jak MethodAsync
lub ToListAsync
), aby outsourcingować trudność. Musimy więc tylko radzić sobie z Async i czekać (co jest łatwe i bardzo podobne do normalnego kodu)
Problem: Szybka zmiana rzeczywistej implementacji normalnego kodu na działanie asynchroniczne: 2 minuty
Linia kodu pokazana poniżej w Warstwie danych zaczęła się łamać (wiele miejsc). Ponieważ zaktualizowaliśmy część naszego kodu z .Net Framework 4.2. * Do .Net core. Musieliśmy to naprawić w ciągu 1 godziny w całej aplikacji!
var myContract = query.Where(c => c.ContractID == _contractID).First();
bułka z masłem!
- Zainstalowaliśmy pakiet nugetowy EntityFramework, ponieważ ma on QueryableExtensions. Albo innymi słowy to nie realizacja asynchroniczny (zadanie), więc może przetrwać z prostymi
Async
i await
w kodzie.
- namespace = Microsoft.EntityFrameworkCore
wywołanie linii kodu zostało zmienione w ten sposób
var myContract = await query.Where(c => c.ContractID == _contractID).FirstAsync();
Zmieniono podpis metody z
Contract GetContract(int contractnumber)
do
async Task<Contract> GetContractAsync(int contractnumber)
wpływ GetContractAsync(123456);
miała również metoda wywoływania: została wywołana jakoGetContractAsync(123456).Result;
Zmienialiśmy to wszędzie w 30 minut!
Ale architekt powiedział nam, aby nie używać biblioteki EntityFramework tylko do tego! ups! dramat! Następnie stworzyliśmy niestandardową implementację Zadania (Fuj). Które wiesz jak. Wciąż łatwe! .. nadal fuj ..
Gdzie teraz?
Jest wspaniały, szybki film, który moglibyśmy obejrzeć o Konwertowaniu wywołań synchronicznych na asynchroniczne w ASP.Net Core , być może jest to kierunek, w którym można pójść po przeczytaniu tego.