Być może czegoś mi brakuje
Ty jesteś.
Jaka jest różnica między robieniem Task.Wait
a await task
?
Lunch zamawiasz u kelnera w restauracji. Chwilę po złożeniu zamówienia wchodzi znajomy, siada obok ciebie i rozpoczyna rozmowę. Teraz masz dwie możliwości. Możesz zignorować przyjaciela, dopóki zadanie nie zostanie zakończone - możesz poczekać, aż pojawi się zupa i nie robić nic innego, czekając. Lub możesz odpowiedzieć swojemu przyjacielowi, a kiedy przyjaciel przestanie mówić, kelner przyniesie ci zupę.
Task.Wait
blokuje do momentu ukończenia zadania - ignorujesz znajomego, dopóki zadanie nie zostanie ukończone. await
przetwarza wiadomości w kolejce komunikatów, a po zakończeniu zadania kolejkuje komunikat z informacją „podnieś tam, gdzie przerwałeś, po tym, aż poczeka”. Rozmawiasz z przyjacielem, a gdy dochodzi do przerwy w rozmowie, przybywa zupa.
Task
10 ms faktycznie wykonało 10-godzinnyTask
wątek, blokując w ten sposób całe 10 godzin?Aby zademonstrować odpowiedź Erica, oto kod:
źródło
//If you press Button2 now you won't see anything in the console until this task is complete and then the label will be updated!
” wprowadza w błąd. Po naciśnięciu przyciskut.Wait();
w module obsługi zdarzeń kliknięcia przyciskuButtonClick()
nie można nic nacisnąć, a następnie wyświetlić czegoś w konsoli i aktualizacji etykiety „do czasu zakończenia tego zadania”, ponieważ GUI jest zawieszone i nie odpowiada, to znaczy kliknięcia lub interakcje z GUI są LOST aż do zakończenia zadania oczekiwaniat.Wait
główny wątek, dopóki zadanie nie zostanie zakończone”.Ten przykład bardzo wyraźnie pokazuje różnicę. Przy async / oczekuj wątek wywołujący nie będzie blokował i kontynuował wykonywanie.
Wyjście DoAsTask:
Wyjście DoAsAsync:
Aktualizacja: ulepszony przykład pokazujący identyfikator wątku na wyjściu.
źródło
Wait (), spowoduje uruchomienie potencjalnie asynchronicznego kodu w sposób zsynchronizowany. czekam nie będzie.
Na przykład masz aplikację internetową asp.net. Użytkownik A wywołuje / punkt końcowy getUser / 1. Pula aplikacji asp.net wybierze wątek z puli wątków (Thread1) i ten wątek wykona połączenie http. Jeśli wykonasz funkcję Wait (), ten wątek zostanie zablokowany do momentu rozwiązania połączenia HTTP. Podczas oczekiwania, jeśli UserB wywoła / getUser / 2, pula aplikacji będzie musiała obsługiwać inny wątek (Thread2), aby ponownie nawiązać połączenie HTTP. Właśnie utworzyłeś (cóż, właściwie pobrany z puli aplikacji) inny wątek bez powodu, ponieważ nie możesz użyć Thread1, został on zablokowany przez Wait ().
Jeśli użyjesz funkcji Oczekiwanie na wątku 1, SyncContext zarządza synchronizacją między wątkiem 1 a połączeniem http. Po prostu powiadomi o zakończeniu połączenia HTTP. W międzyczasie, jeśli UserB wywołuje / getUser / 2, wtedy użyjesz Thread1 ponownie, aby wykonać połączenie HTTP, ponieważ zostało ono zwolnione, gdy czeka na trafienie. Wtedy kolejne żądanie może z niego skorzystać, jeszcze więcej. Po zakończeniu połączenia HTTP (użytkownik 1 lub użytkownik 2) Wątek 1 może uzyskać wynik i powrócić do dzwoniącego (klienta). Wątek 1 był używany do wielu zadań.
źródło
W tym przykładzie praktycznie niewiele. Jeśli czekasz na zadanie, które powraca w innym wątku (np. Wywołanie WCF) lub zrzeka się kontroli nad systemem operacyjnym (takim jak File IO), czekanie zużyje mniej zasobów systemowych, nie blokując wątku.
źródło
W powyższym przykładzie możesz użyć „TaskCreationOptions.HideScheduler” i znacznie zmodyfikować metodę „DoAsTask”. Sama metoda nie jest asynchroniczna, tak jak dzieje się to w przypadku „DoAsAsync”, ponieważ zwraca wartość „Zadanie” i jest oznaczona jako „asynchroniczna”, tworząc kilka kombinacji. W ten sposób daje mi dokładnie to samo, co użycie „asynchronicznie / oczekuj” :
źródło