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ć?
Task
.Odpowiedzi:
Asynchroniczny słów kluczowych pozwala metody korzystania z
await
składni w swej definicji. Mogę użyćawait
dowolnej metody, która zwracaTask
typ, niezależnie od tego, czy jest to metoda asynchroniczna.void
jest legalnym (choć zniechęconym ) typem zwrotu dla metody asynchronicznej, więc dlaczego nie byłby dozwolony? Z zewnątrzasync
nie 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 T
metodą jest metoda, która normalnie powracaT
(który jest ograniczony dovoid
,Task
lubTask<A>
). To, że jest to metoda asynchroniczna, nie jest częścią interfejsu. Zauważ, że następujący kod jest nielegalny:To (lub podobny kod w klasie abstrakcyjnej) generuje następujący komunikat o błędzie w VS2012:
Gdybym nie zamierzają metodę w klasie interfejsu lub dominującej być typowo asynchroniczny, nie mogę używać
async
do komunikowania się tym. Gdybym chciał zaimplementować go za pomocąawait
składni, musiałbym mieć możliwość zastąpienia metod asynchronicznych (w przypadku klasy nadrzędnej).źródło
override
, ale o to właśnie chodzi.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.async
modyfikator 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.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.
źródło