Dlaczego C # pozwala na asynchronizację zastępowania?

16

W języku C #, gdy przesłonisz metodę, dozwolone jest, aby zastąpienie było asynchroniczne, gdy oryginalna metoda nie była. To wygląda na kiepską formę.

Przykładem, który mnie do tego przywiódł, był ten: zostałem sprowadzony, aby pomóc z problemem testu obciążenia. Przy około 500 jednoczesnych użytkownikach proces logowania rozpadłby się w pętli przekierowań. Usługi IIS rejestrowały wyjątki z komunikatem „Moduł asynchroniczny lub moduł obsługi zakończono, gdy operacja asynchroniczna była nadal w toku”. Poszukiwania doprowadziły mnie do wniosku, że ktoś znęcał się async void, ale moje szybkie przeszukanie źródła nic nie dało .

Niestety szukałem „asynchronizacji” (wyszukiwanie wyrażeń regularnych), kiedy powinienem szukać czegoś bardziej podobnego do „asynchronizacji [^ T]” (zakładając, że zadanie nie było w pełni kwalifikowane… masz rację).

Później znalazłem async override void onActionExecuting(...w kontrolerze podstawowym. Oczywiście to musiał być problem i tak było. Naprawienie tego problemu (na chwilę synchronizacja) rozwiązało problem.

Powrót do pytania: dlaczego och, dlaczego można oznaczyć zastąpienie jako asynchroniczne, gdy kod wywołujący nigdy nie może na niego czekać?

Peter T. LaComb Jr.
źródło
Co dokładnie powstrzymuje rozmówcę przed oczekiwaniem na zastąpioną metodę? Nie widzę przeszkody.
Martin Maat,
@MartinMaat Możesz tylko czekać na metody, które powrócą Task.
Derek Elkins opuścił SE
Być może to niezły punkt, którego nie zauważyłem. Muszę to sprawdzić, ale nie przypominam sobie ostrzeżenia VS o wywołaniu metod niesynchronicznych bez oczekiwania.
Peter T. LaComb Jr.

Odpowiedzi:

16

Asynchroniczny słów kluczowych pozwala metody korzystania z awaitskładni w swej definicji. Mogę użyć awaitdowolnej metody, która zwraca Tasktyp, niezależnie od tego, czy jest to metoda asynchroniczna.

voidjest legalnym (choć zniechęconym ) typem zwrotu dla metody asynchronicznej, więc dlaczego nie byłby dozwolony? Z zewnątrz asyncnie umożliwia nic, bez czego nie można się obejść. Metodę, z którą masz problem, można napisać, aby zachowywała się dokładnie tak samo bez asynchronizacji. Jego definicja byłaby bardziej szczegółowa.

Dzwoniącym An async Tmetodą jest metoda, która normalnie powraca T(który jest ograniczony do void, Tasklub Task<A>). To, że jest to metoda asynchroniczna, nie jest częścią interfejsu. Zauważ, że następujący kod jest nielegalny:

interface IFoo {
    async void Bar();
}

To (lub podobny kod w klasie abstrakcyjnej) generuje następujący komunikat o błędzie w VS2012:

Modyfikatora „asynchronicznego” można używać tylko w metodach, które mają treść instrukcji

Gdybym nie zamierzają metodę w klasie interfejsu lub dominującej być typowo asynchroniczny, nie mogę używać asyncdo komunikowania się tym. Gdybym chciał zaimplementować go za pomocą awaitskładni, musiałbym mieć możliwość zastąpienia metod asynchronicznych (w przypadku klasy nadrzędnej).

Derek Elkins opuścił SE
źródło
1
W ogóle nie wspominasz override, ale o to właśnie chodzi.
Nathan Tuggy,
5
@NathanTuggy Sedno odpowiedzi polega na tym, asyncże nie zmienia on interfejsu metody, a jedynie to, co jest dozwolone składniowo w jej definicji, więc to, czy jest to zastąpienie, czy nie, jest całkowicie nieistotne.
Derek Elkins opuścił SE
1
Należy wyjaśnić , że zamiast zakładając, każdy już wie wszystko istotne.
Nathan Tuggy,
2
@NathanTuggy Czuję, że to wyjaśniłem. Czy możesz zadać konkretne pytanie, co do którego jesteś zdezorientowany lub wyobrażasz sobie, że zadałaby go inna zdezorientowana osoba? Jedyne, co mogę dodać, to wskazać, że asyncmodyfikator można zastosować tylko do implementacji. Nie można zadeklarować metody asynchronicznej w interfejsie, na przykład podkreślając, że to, czy metoda jest asynchroniczna, czy nie, nie jest częścią interfejsu.
Derek Elkins opuścił SE
5
Mam na myśli wyjaśnienie w odpowiedzi . Nie po to są komentarze na dłuższą metę.
Nathan Tuggy,
10

Jedynym celem słowa kluczowego async jest sprawienie, aby oczekiwanie w treści tej funkcji było słowem kluczowym. Jest to konieczne, aby dodanie funkcji oczekiwania nie spowodowało uszkodzenia istniejącego kodu. Microsoft zdecydował się skorzystać z opcji oczekiwania na opcję opt-in. W przypadku funkcji, która nie jest oznaczona jako asynchroniczna, można zdefiniować zmienną o nazwie czekaj bez problemu.

Dlatego asynchronizacja nie jest częścią podpisu funkcji i nie ma semantycznego znaczenia w generowanym kodzie IL. Kompilator dokładnie wie, jak poprawnie skompilować funkcję. Poleca także kompilatorowi, aby zwracał tylko Zadanie, Zadanie <T> lub void.

Eric Johnson
źródło