Jak mogę czekać, aż void async
metoda zakończy swoją pracę?
na przykład mam funkcję jak poniżej:
async void LoadBlahBlah()
{
await blah();
...
}
teraz chcę się upewnić, że wszystko zostało załadowane, zanim przejdę do innego miejsca.
c#
asynchronous
MBZ
źródło
źródło
await Task.Run(() => An_async_void_method_I_can_not_modify_now())
await Task.Run(() => blah())
wprowadza w błąd. To nie czeka na zakończenie funkcji asynchronicznejblah
, tylko czeka na (trywialne) utworzenie zadania i jest kontynuowane bezpośrednio przedblah()
zakończeniem.Thread.Sleep
nie jest asynchroniczne. To pytanie dotyczy oczekiwania naasync void
funkcję, powiedzmyasync void blah() { Task.Delay(10000); }
Jeśli możesz zmienić podpis swojej funkcji na
async Task
, możesz użyć przedstawionego tutaj koduźródło
Najlepszym rozwiązaniem jest użycie
async Task
. Należy tego unikaćasync void
z kilku powodów, z których jednym jest składalność.Jeśli metoda nie może powrócić
Task
(np. Jest to program obsługi zdarzenia), możesz użyćSemaphoreSlim
sygnału metody, gdy ma zamiar zakończyć. Rozważ zrobienie tego wfinally
bloku.źródło
wykonaj AutoResetEvent, wywołaj funkcję, a następnie poczekaj na AutoResetEvent, a następnie ustaw ją w async void, gdy wiesz, że jest wykonana.
Możesz także poczekać na zadanie, które wróci z Twojej pustej asynchronicznej
źródło
Naprawdę nie musisz nic robić ręcznie,
await
słowo kluczowe wstrzymuje wykonywanie funkcji do czasublah()
powrotu.T
jest typemblah()
zwracanego obiektuNie można naprawdę funkcja więc może nie być
await
void
LoadBlahBlah()
void
źródło
LoadBlahBlah()
zakończenie, a nieblah()
Wiem, że to stare pytanie, ale wciąż jest to problem, do którego wciąż wkraczam, a mimo to nadal nie ma jasnego rozwiązania, aby zrobić to poprawnie, używając async / await w metodzie async void signature.
Jednak zauważyłem, że .Wait () działa poprawnie wewnątrz metody void.
a ponieważ async void i void mają ten sam podpis, może być konieczne wykonanie następujących czynności.
Dość myląco async / await nie blokuje następnego kodu.
Kiedy dekompilujesz swój kod, przypuszczam, że async void tworzy wewnętrzne zadanie (podobnie jak async Task), ale ponieważ podpis nie obsługuje zwracania tych wewnętrznych zadań
oznacza to, że wewnętrznie metoda async void nadal będzie mogła „oczekiwać” wewnętrznie asynchronicznych metod. ale zewnętrznie nie jest w stanie wiedzieć, kiedy zadanie wewnętrzne jest zakończone.
Mój wniosek jest taki, że async void działa zgodnie z przeznaczeniem, a jeśli potrzebujesz informacji zwrotnej z wewnętrznego zadania, musisz zamiast tego użyć podpisu async Task.
mam nadzieję, że moje wędrówki mają sens dla każdego, kto szuka odpowiedzi.
Edycja: stworzyłem przykładowy kod i zdekompilowałem go, aby zobaczyć, co się właściwie dzieje.
Zamienia się w (edytuj: wiem, że kod ciała nie jest tutaj, ale w statemachines, ale statemachines był w zasadzie identyczny, więc nie zawracałem sobie głowy dodawaniem ich)
ani AsyncVoidMethodBuilder, ani AsyncTaskMethodBuilder w rzeczywistości nie mają żadnego kodu w metodzie Start, który wskazywałby na ich blokowanie i zawsze byłyby uruchamiane asynchronicznie po ich uruchomieniu.
co oznacza, że bez zwracającego zadania nie byłoby możliwości sprawdzenia, czy zostało ono zakończone.
zgodnie z oczekiwaniami uruchamia tylko zadanie działające asynchronicznie, a następnie kontynuuje je w kodzie. i zadanie asynchroniczne, najpierw uruchamia zadanie, a następnie zwraca je.
więc myślę, że moją odpowiedzią byłoby nigdy nie używać async void, jeśli chcesz wiedzieć, kiedy zadanie jest wykonane, do tego służy Async Task.
źródło