Po pewnym czasie zajmowania się wzorcem asynchronizacji / oczekiwania w języku C # nagle zdałem sobie sprawę, że tak naprawdę nie wiem, jak wyjaśnić, co dzieje się w następującym kodzie:
async void MyThread()
{
while (!_quit)
{
await GetWorkAsync();
}
}
GetWorkAsync()
zakłada się, że zwróci oczekiwany element, Task
który może, ale nie musi, spowodować przełączenie wątku podczas kontynuacji.
Nie byłbym zdezorientowany, gdyby oczekiwanie nie było w pętli. Naturalnie oczekiwałbym, że reszta metody (tj. Kontynuacja) potencjalnie zadziała w innym wątku, co jest w porządku.
Jednak wewnątrz pętli koncepcja „reszty metody” staje się dla mnie nieco mglista.
Co stanie się z „resztą pętli”, jeśli wątek zostanie włączony w kontynuacji, a jeśli nie zostanie przełączony? W którym wątku wykonywana jest następna iteracja pętli?
Moje obserwacje pokazują (niepotwierdzone jednoznacznie), że każda iteracja rozpoczyna się w tym samym wątku (oryginalnym), podczas gdy kontynuacja jest wykonywana w innym. Czy to może być naprawdę? Jeśli tak, to czy jest to stopień nieoczekiwanej równoległości, który należy uwzględnić w odniesieniu do bezpieczeństwa wątków metody GetWorkAsync?
AKTUALIZACJA: Moje pytanie nie jest duplikatem, jak niektórzy sugerują. while (!_quit) { ... }
Wzór kod jest jedynie uproszczenie mojego aktualnego kodu. W rzeczywistości mój wątek jest długotrwałą pętlą, która przetwarza swoją kolejkę wprowadzania elementów pracy w regularnych odstępach czasu (domyślnie co 5 sekund). Rzeczywista kontrola warunków wyjścia nie jest również prostą kontrolą pola, jak sugeruje przykładowy kod, ale raczej kontrolą uchwytu zdarzenia.