Z mojego zrozumienia jednej z głównych rzeczy, które async
iawait
zrobić, jest wykonanie kodu łatwo pisać i czytać - ale jest ich użyciem równać do tarła wątki tła wykonywać długiego trwania logiki?
Obecnie wypróbowuję najbardziej podstawowy przykład. Dodałem kilka komentarzy. Czy możesz mi to wyjaśnić?
// I don't understand why this method must be marked as `async`.
private async void button1_Click(object sender, EventArgs e)
{
Task<int> access = DoSomethingAsync();
// task independent stuff here
// this line is reached after the 5 seconds sleep from
// DoSomethingAsync() method. Shouldn't it be reached immediately?
int a = 1;
// from my understanding the waiting should be done here.
int x = await access;
}
async Task<int> DoSomethingAsync()
{
// is this executed on a background thread?
System.Threading.Thread.Sleep(5000);
return 1;
}
c#
.net
asynchronous
async-await
Dan Dinu
źródło
źródło
Odpowiedzi:
Podczas używania
async
iawait
kompilator generuje maszynę stanu w tle.Oto przykład, na którym, mam nadzieję, wyjaśnię niektóre szczegóły dotyczące wysokiego poziomu:
OK, więc co się tutaj dzieje:
Task<int> longRunningTask = LongRunningOperationAsync();
zaczyna się wykonywaćLongRunningOperation
Niezależna praca jest wykonywana, załóżmy, że główny wątek (identyfikator wątku = 1)
await longRunningTask
zostanie osiągnięty.Teraz, jeśli
longRunningTask
nie zakończyło się i nadal działa,MyMethodAsync()
powróci do metody wywoływania, więc główny wątek nie zostanie zablokowany. Po zakończeniulongRunningTask
wątek z ThreadPool (może być dowolnym wątkiem) powróci doMyMethodAsync()
poprzedniego kontekstu i będzie kontynuował wykonywanie (w tym przypadku drukowanie wyniku na konsoli).Drugi przypadek polegałby na tym, że proces
longRunningTask
już zakończył się, a wynik jest dostępny. Po osiągnięciu tegoawait longRunningTask
mamy już wynik, więc kod będzie nadal działał w tym samym wątku. (w tym przypadku wynik drukowania do konsoli). Oczywiście nie jest tak w przypadku powyższego przykładu, w którym jestTask.Delay(1000)
zaangażowany.źródło
Mają na celu ułatwienie pisania i czytania kodu asynchronicznego , tak.
Ani trochę.
Słowo
async
kluczowe włączaawait
słowo kluczowe. Tak więc każda zastosowana metodaawait
musi zostać oznaczonaasync
.Nie, ponieważ
async
metody nie są domyślnie uruchamiane w innym wątku.Nie.
Pomocne może okazać się moje
async
/await
wprowadzenie . W oficjalnych docs MSDN są również wyjątkowo dobre (szczególnie TAP fragment), aasync
zespół zgasić doskonałą nas .źródło
async
metody nie są domyślnie uruchamiane w innym wątku. W twoim przykładzieSleep()
wywołanie wewnątrzDoSomethingAsync()
blokuje bieżący wątek, co uniemożliwia kontynuowanie wykonywaniabutton1_Click()
do momentuDoSomethingAsync()
zakończenia. Zwróć uwagę, że podczas gdyThread.Sleep()
blokuje wykonywany wątek,Task.Delay() does not.
Wyjaśnienie
Oto szybki przykład
async
/await
na wysokim poziomie. Jest o wiele więcej szczegółów do rozważenia poza tym.Uwaga:
Task.Delay(1000)
symuluje wykonywanie pracy przez 1 sekundę. Myślę, że najlepiej myśleć o tym jako o czekaniu na odpowiedź z zewnętrznego źródła. Ponieważ nasz kod czeka na odpowiedź, system może odłożyć uruchomione zadanie na bok i wrócić do niego po zakończeniu. Tymczasem może wykonać inne prace nad tym wątkiem.W poniższym przykładzie robi to dokładnie pierwszy blok . Natychmiast rozpoczyna wszystkie zadania (
Task.Delay
linie) i odsuwa je na bok. Kod zatrzyma się naawait a
linii, dopóki nie upłynie 1 sekundowe opóźnienie przed przejściem do następnej linii. Ponieważb
,c
,d
, ae
wszystko zaczęło się wykonanie w prawie dokładnie w tym samym czasie, coa
(z powodu braku czekają), powinny zakończyć się w przybliżeniu w tym samym czasie w tej sprawie.W poniższym przykładzie drugi blok uruchamia zadanie i czeka na jego zakończenie (czyli co się
await
dzieje) przed rozpoczęciem kolejnych zadań. Każda iteracja zajmuje 1 sekundę.await
Jest wstrzymywanie programu i czeka na wynik przed kontynuowaniem. Jest to główna różnica między pierwszym a drugim blokiem.Przykład
WYNIK:
Dodatkowe informacje dotyczące SynchronizationContext
Uwaga: w tym momencie sprawy stają się dla mnie trochę mgliste, więc jeśli coś jest w błędzie, popraw mnie, a ja zaktualizuję odpowiedź. Ważne jest, aby mieć podstawową wiedzę na temat tego, jak to działa, ale możesz sobie z tym poradzić, nie będąc ekspertem w tej dziedzinie, dopóki nie będziesz go używać
ConfigureAwait(false)
, chociaż prawdopodobnie stracisz szansę na optymalizację, zakładam.Jest jeden aspekt tego, co sprawia, że koncepcja
async
/ jestawait
nieco trudniejsza do zrozumienia. Faktem jest, że w tym przykładzie wszystko dzieje się w tym samym wątku (lub przynajmniej w tym samym wątku, który wydaje się być tym samym wątkiemSynchronizationContext
). Domyślnieawait
przywróci kontekst synchronizacji oryginalnego wątku, na którym był uruchomiony. Na przykład w ASP.NET maszHttpContext
powiązanie z wątkiem, gdy przychodzi żądanie. Ten kontekst zawiera rzeczy specyficzne dla oryginalnego żądania HTTP, takie jak oryginalny obiekt żądania, który ma takie elementy jak język, adres IP, nagłówki itp. Jeśli przełączysz wątki w połowie przetwarzania, możesz potencjalnie skończyć z próbą wyciągnięcia informacji z tego obiektu na inny obiektHttpContext
co może być katastrofalne. Jeśli wiesz, że do niczego nie będziesz używać kontekstu, możesz „nie przejmować się” tym. Zasadniczo pozwala to na uruchamianie kodu w osobnym wątku bez konieczności przybliżania kontekstu.Jak to osiągasz? Domyślnie
await a;
kod faktycznie zakłada, że chcesz przechwycić i przywrócić kontekst:Jeśli chcesz pozwolić głównemu kodowi na kontynuowanie w nowym wątku bez oryginalnego kontekstu, po prostu użyj false zamiast true, aby wiedzieć, że nie musi on przywracać kontekstu.
Po zakończeniu pauzy program będzie kontynuował potencjalnie na zupełnie innym wątku z innym kontekstem. Stąd pochodziłaby poprawa wydajności - mogłaby być kontynuowana w dowolnym dostępnym wątku bez konieczności przywracania pierwotnego kontekstu, z którym zaczęła.
Czy to jest mylące? O tak! Czy potrafisz to rozgryźć? Prawdopodobnie! Po zapoznaniu się z pojęciami przejdź do wyjaśnień Stephena Cleary'ego, które są bardziej ukierunkowane na kogoś, kto ma techniczne zrozumienie
async
/await
już.źródło
await MethodCall()
to absolutna strata? Równie dobrze możesz upuścićawait
/async
?await
, myślę, że zwalnia wątek z powrotem do puli zamiast go trzymać. Dzięki temu jest dostępny do użycia w innym miejscu w oczekiwaniu na zwrot zadaniaOprócz innych odpowiedzi, spójrz na czekaj (C # Reference)
a dokładniej na dołączonym przykładzie, to trochę wyjaśnia twoją sytuację
źródło
Task.Delay
pożary.Wyświetlanie powyższych wyjaśnień w działaniu w prostym programie konsoli:
Wyjście to:
A zatem,
TestAsyncAwaitMethods
. To natychmiast powraca bez zatrzymywania bieżącego wątku i natychmiast pojawia się komunikat „Naciśnij dowolny klawisz, aby wyjść”LongRunningMethod
działa w tle. Po zakończeniu inny wątek z Threadpool wychwytuje ten kontekst i wyświetla końcowy komunikatZatem nie wątek jest zablokowany.
źródło
return 1
część zasługuje na dodatkowe wyjaśnienie:await
słowo kluczowe pozwala bezpośrednio zwrócić podstawowy typTask<T>
, co ułatwia dostosowanie wychodzącego kodu do świata oczekujących / asynchronicznych . Ale nie musisz zwracać wartości, ponieważ możliwe jest zwrócenie wartościTask
bez określania zwracanego typu, który byłby odpowiednikiemvoid
metody synchronicznej . Pamiętaj, że C # pozwala naasync void
metody, ale powinieneś tego unikać, chyba że zajmujesz się obsługą zdarzeń.Myślę, że wybrałeś zły przykład
System.Threading.Thread.Sleep
Celem
async
zadania jest umożliwienie mu wykonywania w tle bez blokowania głównego wątku, na przykład robieniaDownloadFileAsync
System.Threading.Thread.Sleep
nie jest czymś, co „jest zrobione”, po prostu śpi, dlatego twoja kolejna linia jest osiągana po 5 sekundach ...Przeczytaj ten artykuł, myślę, że jest to świetne wyjaśnienie
async
iawait
koncepcja: http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspxźródło
Thread.Sleep
blokuje wątek (wątek nie może zrobić nic innego, jak siedzieć bezczynnie), ale metoda asynchroniczna tego nie robi. W przypadkuDownloadFileAsync
wątku można przejść i zrobić coś innego, dopóki odpowiedź nie zostanie wysłana ze zdalnego serwera. Lepszym symbolem zastępczym dla „jakiegoś zadania wymagającego czasu” w metodzie asynchronicznej jest toTask.Delay
, że jest to tak naprawdę asynchroniczne.async
słowa kluczowego. Ale jego metoda wciąż działała synchronicznie, a ta odpowiedź doskonale wyjaśniała dlaczego: ponieważ tak naprawdę nie uruchomił żadnego kodu asynchronicznego. Oznaczone metodyasync
nadal działają synchronicznie aż do momentu, gdy będzieszawait
niekompletnyTask
. Jeśli nieawait
, metoda działa synchronicznie, a kompilator ostrzeże Cię o tym.Oto szybki program konsoli, aby wyjaśnić tym, którzy go śledzą. Ta
TaskToDo
metoda jest długotrwałą metodą asynchroniczną. Uruchomienie asynchroniczne odbywa sięTestAsync
metodą Metoda pętli testowych po prostu uruchamiaTaskToDo
zadania i uruchamia je asynchronicznie. Widać to w wynikach, ponieważ nie wykonują się one w tej samej kolejności od uruchomienia do uruchomienia - po zakończeniu zgłaszają się do wątku interfejsu użytkownika konsoli. Uproszczone, ale myślę, że uproszczone przykłady lepiej wydobywają rdzeń wzoru niż przykłady bardziej zaangażowane:źródło
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:
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:
await
async
(obowiązkowa składnia)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 tutajPodziel 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ż zbudowanejMethodAsync()
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
lubToListAsync
), 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!
bułka z masłem!
Async
iawait
w kodzie.wywołanie linii kodu zostało zmienione w ten sposób
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.
źródło
Wszystkie odpowiedzi tutaj
Task.Delay()
lub inne wbudowaneasync
funkcje. Ale oto mój przykład, który nie korzysta z żadnej z tychasync
funkcji:źródło
task.Wait();
i jak można go użyć, aby uniknąć asynchronizacji / czekać na piekło: PTa odpowiedź ma na celu dostarczenie pewnych informacji specyficznych dla ASP.NET.
Korzystając z asynchronizacji / oczekiwania na kontroler MVC, można zwiększyć wykorzystanie puli wątków i osiągnąć znacznie lepszą przepustowość, jak wyjaśniono w poniższym artykule,
http://www.asp.net/mvc/tutorials/mvc-4/using-asynchronous-methods-in-aspnet-mvc-4
źródło
Asynchronizuj i czekaj na proste objaśnienie
Prosta analogia
Osoba może poczekać na poranny pociąg. To wszystko, co robią, ponieważ jest to ich główne zadanie, które obecnie wykonują. (programowanie synchroniczne (co zwykle robisz!))
Inna osoba może poczekać na poranny pociąg, podczas gdy pali papierosa, a następnie pije kawę. (Programowanie asynchroniczne)
Co to jest programowanie asynchroniczne?
Programowanie asynchroniczne polega na tym, że programista zdecyduje się uruchomić część swojego kodu w innym wątku niż główny wątek wykonania, a następnie powiadomi główny wątek o zakończeniu.
Co faktycznie robi słowo kluczowe asynchroniczne?
Prefiks słowa kluczowego async w nazwie metody takiej jak
pozwala programiście używać słowa kluczowego „czekaj” podczas wywoływania zadań asynchronicznych. To wszystko, co robi.
Dlaczego to jest ważne?
W wielu systemach oprogramowania główny wątek jest zarezerwowany dla operacji związanych konkretnie z interfejsem użytkownika. Jeśli korzystam z bardzo złożonego algorytmu rekurencyjnego, którego wykonanie zajmuje 5 sekund na moim komputerze, ale uruchamiam go w głównym wątku (wątek interfejsu użytkownika). Gdy użytkownik spróbuje kliknąć dowolny element mojej aplikacji, będzie wyglądał na zawieszony ponieważ mój główny wątek ustawił się w kolejce i przetwarza obecnie zbyt wiele operacji. W rezultacie główny wątek nie może przetworzyć kliknięcia myszy, aby uruchomić metodę z kliknięcia przycisku.
Kiedy używasz Async i Oczekujesz?
Używaj asynchronicznych słów kluczowych idealnie, gdy robisz coś, co nie wymaga interfejsu użytkownika.
Powiedzmy, że piszesz program, który pozwala użytkownikowi na szkicowanie na telefonie komórkowym, ale co 5 sekund będzie sprawdzał pogodę w Internecie.
Powinniśmy czekać na połączenie z pollingiem co 5 sekund do sieci, aby uzyskać pogodę, ponieważ użytkownik aplikacji musi kontynuować interakcję z mobilnym ekranem dotykowym, aby rysować ładne zdjęcia.
Jak korzystać z Async i Oczekuj
Kontynuując powyższy przykład, oto pseudo kod, jak go napisać:
Dodatkowe uwagi - aktualizacja
Zapomniałem wspomnieć w moich oryginalnych notatkach, że w języku C # możesz oczekiwać tylko metod zapakowanych w Zadania. na przykład możesz poczekać na tę metodę:
Nie możesz oczekiwać metod, które nie są zadaniami takimi jak to:
Tutaj możesz przejrzeć kod źródłowy klasy Task .
źródło
Async / Await
W rzeczywistości Async / Await to para słów kluczowych, które są po prostu cukrem syntaktycznym do tworzenia wywołania zwrotnego zadania asynchronicznego.
Weź przykład z tej operacji:
Powyższy kod ma kilka wad. Błędy nie są przekazywane i trudno je odczytać. Ale Async i Await przychodzą, aby nam pomóc:
Oczekiwania na wywołania muszą odbywać się w metodach asynchronicznych. Ma to pewne zalety:
UWAGA : Async i Await są używane z wywołaniami asynchronicznymi, aby ich nie wykonywać. W tym celu musisz użyć Task Libary , takiego jak Task.Run ().
Oto porównanie rozwiązań oczekujących i oczekujących
Oto rozwiązanie asynchroniczne:
To jest metoda asynchroniczna:
Możesz wywołać metodę asynchroniczną bez słowa kluczowego Oczekiwanie, ale oznacza to, że wszelkie wyjątki tutaj są połykane w trybie zwolnienia:
Async i Await nie są przeznaczone do obliczeń równoległych. Służą do nie blokowania głównego wątku. Jeśli chodzi o aplikacje asp.net lub Windows, blokowanie głównego wątku z powodu połączenia sieciowego jest złą rzeczą. Jeśli to zrobisz, aplikacja przestanie odpowiadać, a nawet ulegnie awarii.
Sprawdź MS Docs, aby uzyskać więcej przykładów.
źródło
Szczerze mówiąc, nadal uważam, że najlepszym wytłumaczeniem jest przyszłość i obietnice na Wikipedii: http://en.wikipedia.org/wiki/Futures_and_promises
Podstawową ideą jest to, że masz osobną pulę wątków, które wykonują zadania asynchronicznie. Podczas korzystania z niego. Obiekt jednak obiecuje, że wykona operację w pewnym momencie i da ci wynik, gdy o to poprosisz. Oznacza to, że blokuje się, gdy zażądasz wyniku i nie został on zakończony, ale w przeciwnym razie zostanie wykonany w puli wątków.
Stamtąd możesz zoptymalizować rzeczy: niektóre operacje można zaimplementować asynchronicznie, a także zoptymalizować takie rzeczy, jak operacje we / wy pliku i komunikacja sieciowa, grupując kolejne żądania i / lub zmieniając ich kolejność. Nie jestem pewien, czy jest to już w ramach zadań Microsoftu - ale jeśli tak nie jest, byłoby to jedną z pierwszych rzeczy, które chciałbym dodać.
Możesz faktycznie zaimplementować przyszłe sortowanie wzorów z wydajnością w C # 4.0. Jeśli chcesz wiedzieć, jak to dokładnie działa, mogę polecić ten link, który wykonuje przyzwoitą robotę: http://code.google.com/p/fracture/source/browse/trunk/Squared/TaskLib/ . Jeśli jednak zaczniesz się z tym bawić, zauważysz, że naprawdę potrzebujesz pomocy językowej, jeśli chcesz robić wszystkie fajne rzeczy - dokładnie to zrobiła Microsoft.
źródło
Zobacz ten skrzypce https://dotnetfiddle.net/VhZdLU (i popraw go, jeśli to możliwe), aby uruchomić prostą aplikację konsolową, która pokazuje użycie Task, Task.WaitAll (), asynchronizuje i oczekuje na operatorów w tym samym programie.
To skrzypce powinno wyczyścić koncepcję cyklu realizacji.
Oto przykładowy kod
Śledzenie pochodzące z okna wyjściowego:
źródło
źródło
Na wyższym poziomie:
1) Słowo kluczowe Async umożliwia oczekiwanie i to wszystko, co robi. Słowo kluczowe asynchroniczne nie uruchamia metody w osobnym wątku. Początkowa metoda asynchroniczna działa synchronicznie, dopóki nie trafi w oczekiwanie na czasochłonne zadanie.
2) Możesz poczekać na metodę zwracającą Zadanie lub Zadanie typu T. Nie możesz czekać na metodę async void.
3) W chwili, gdy główny wątek napotka na czasochłonne zadanie lub gdy rozpocznie się faktyczna praca, główny wątek powraca do programu wywołującego bieżącą metodę.
4) Jeśli główny wątek oczekuje na zadanie, które jest nadal wykonywane, nie czeka na nie i wraca do programu wywołującego bieżącą metodę. W ten sposób aplikacja pozostaje responsywna.
5) Oczekiwanie na zadanie przetwarzania, będzie teraz wykonywane w innym wątku niż pula wątków.
6) Po zakończeniu tego zadania oczekującego cały kod poniżej zostanie wykonany przez osobny wątek
Poniżej znajduje się przykładowy kod. Wykonaj go i sprawdź identyfikator wątku
źródło
Tak jak ja to rozumiem też, nie powinno być trzeci termin dodaje się do mieszanki:
Task
.Async
to tylko kwalifikator, który umieścisz w metodzie, aby powiedzieć, że jest to metoda asynchroniczna.Task
jest zwrotemasync
funkcji. Wykonuje się asynchronicznie.Jesteś
await
zadaniem. Gdy wykonanie kodu dojdzie do tej linii, sterowanie przeskakuje z powrotem do osoby dzwoniącej z otaczającej oryginalnej funkcji.Jeśli zamiast tego przypiszesz powrót
async
funkcji (tj.Task
) Do zmiennej, gdy wykonanie kodu dojdzie do tego wiersza, to po prostu przechodzi poza ten wiersz w otaczającej funkcji, podczas gdyTask
wykonuje się asynchronicznie.źródło
W tym artykule MDSN: Programowanie asynchroniczne z asynchronią i oczekiwaniem (C #) wyraźnie to wyjaśnia:
źródło
W poniższym kodzie metoda HttpClient GetByteArrayAsync zwraca zadanie getContentsTask. Zadanie jest obietnicą utworzenia rzeczywistej tablicy bajtów po zakończeniu zadania. Operator oczekujący jest stosowany do getContentsTask w celu zawieszenia wykonania w SumPageSizesAsync do momentu ukończenia getContentsTask. W międzyczasie kontrola jest zwracana do programu wywołującego SumPageSizesAsync. Po zakończeniu getContentsTask wyrażenie oczekujące przekształca się w tablicę bajtów.
źródło
Poniżej znajduje się kod, który czyta plik programu Excel przez otwarcie okna dialogowego, a następnie używa asynchronizacji i czeka na uruchomienie asynchronicznego kodu, który odczytuje jeden po drugim wiersz z programu Excel i łączy się z siatką
źródło
Odpowiedzi tutaj są przydatne jako ogólne wskazówki dotyczące oczekiwania / asynchronizacji. Zawierają również pewne szczegóły dotyczące tego, jak połączenie oczekujące / asynchroniczne jest podłączone. Chciałbym podzielić się z Tobą praktycznymi doświadczeniami, które powinieneś wiedzieć przed użyciem tego wzoru.
Termin „czekaj” jest dosłowny, więc jakikolwiek wątek, który go wywołasz, poczeka na wynik metody przed kontynuowaniem. W wątku pierwszego planu jest to katastrofa . Wątek na pierwszym planie niesie ciężar tworzenia aplikacji, w tym widoków, modeli widoków, początkowych animacji i wszystkiego innego, co masz związane z tymi elementami. Więc kiedy czekasz na wątek pierwszego planu, zatrzymujesz aplikację. Użytkownik czeka i czeka, aż nic się nie wydarzy. Zapewnia to negatywne wrażenia użytkownika.
Z pewnością możesz poczekać na wątek w tle, używając różnych środków:
Pełny kod tych uwag znajduje się na stronie https://github.com/marcusts/xamarin-forms-annoyances . Zobacz rozwiązanie o nazwie AwaitAsyncAntipattern.sln.
Witryna GitHub zawiera również łącza do bardziej szczegółowej dyskusji na ten temat.
źródło
async / await
to cukier składniowy do wywołań zwrotnych, nie ma on nic wspólnego z wątkami. msdn.microsoft.com/en-us/magazine/hh456401.aspx Dotyczy kodu niezwiązanego z procesorem, np. oczekiwania na wejście lub opóźnienia.Task.Run
powinien być używany tylko w przypadku kodu związanego z procesorem blog.stephencleary.com/2013/10/…The term "await" is literal, so whatever thread you call it on will wait for the result of the method before continuing.
To nieprawda - może miałeś na myśli Task.Wait ()? Gdy używaszawait
, ustawia resztę metody jako kontynuację, która zostanie wykonana po zakończeniu tego, czego oczekujesz. Wychodzi z metody, w której go użyłeś, aby osoba dzwoniąca mogła kontynuować. Następnie, gdy oczekiwana linia jest rzeczywiście kompletna, kończy resztę tej metody w jakimś wątku (zwykle wątku roboczym).async/await
dotyczy uwolnienia wątków .NET. Gdyawait
operacja jest naprawdę asynchroniczna (na przykład File.WriteAsync .NET.), Zawiesza pozostałą część użytej metodyawait
, aby program wywołujący mógł kontynuować i potencjalnie zakończyć swój cel. Brak wątków blokujących lub oczekujących naawait
operację -ed. Po zakończeniu edytowanej operacjiawait
pozostała częśćasync/await
metody jest umieszczana w wątku i wykonywana (podobnie jak pomysł wywołania zwrotnego).