Udostępnij za pośrednictwem


Usuwanie błędów i ostrzeżeń w metodach asynchronicznych korzystających z operatora await

W tym artykule opisano następujące błędy kompilatora:

  • CS1983: Ponieważ jest to metoda asynchronizna, wyrażenie zwracane musi mieć typ "T", a nie "Task<T>".
  • CS1985: Nie można używać 'await' wewnątrz klauzuli catch.
  • CS1986: "await" wymaga, aby typ miał odpowiednią metodę "GetAwaiter".
  • CS1989: Nie można przekonwertować asynchronicznych wyrażeń lambda na drzewa wyrażeń.
  • CS1991: "Typ" nie może zaimplementować zdarzenia "event", ponieważ jest to zdarzenie środowiska uruchomieniowego systemu Windows i "zdarzenie" jest zwykłym zdarzeniem platformy .NET.
  • CS1992: Operator "await" może być używany tylko w przypadku, gdy znajduje się w metodzie lub wyrażeniu lambda oznaczonym modyfikatorem "async".
  • CS1994: Modyfikator "async" może być używany tylko w metodach, które mają treść.
  • CS1995: Operator "await" może być używany tylko w wyrażeniu zapytania w pierwszym wyrażeniu kolekcji początkowej klauzuli "from" lub w wyrażeniu kolekcji klauzuli "join".
  • CS1996: Nie można używać 'await' w treści instrukcji lock.
  • CS1997: Ponieważ funkcja jest metodą asynchronikową, która zwraca wartość, słowo kluczowe zwracane nie może być zgodne z wyrażeniem obiektu.
  • CS1998: Ta metoda asynchroniczna nie zawiera operatorów "await" i będzie uruchamiana synchronicznie. Rozważ użycie operatora "await", aby oczekiwać na nieblokacyjne wywołania interfejsu API lub "await Task.Run(...)", aby wykonać pracę związaną z procesorem CPU w wątku w tle.
  • CS4001: Nie można oczekiwać na wyrażenie.
  • CS4003: "await" nie może być używany jako identyfikator w metodzie asynchronicznej lub wyrażeniu lambda.
  • CS4005: Metody asynchroniczne nie mogą mieć parametrów typu wskaźnika.
  • CS4006: __arglist nie jest dozwolona na liście parametrów metod asynchronicznych.
  • CS4007: Nie można zachować wystąpienia typu w granicach "await" lub "yield".
  • CS4008: Nie można oczekiwać "void".
  • CS4009: Punkt wejścia nie może być asynchroniczny, jeśli zwraca typ void lub int.
  • CS4010: Nie można przekonwertować wyrażenia asynchronicznego na typ delegata. Wyrażenie asynchroniczne może zwracać wartość void, Task lub Task<T>, z których żaden nie jest konwertowany na typ.
  • pl-PL: CS4011: 'await' wymaga, aby zwracany typ '{1}.GetAwaiter()' miał odpowiednich członków: 'IsCompleted', 'OnCompleted' i 'GetResult', oraz implementował 'INotifyCompletion' lub 'ICriticalNotifyCompletion'.
  • CS4012: Nie można zadeklarować parametrów typu w metodach asynchronicznych ani asynchronicznych wyrażeniach lambda.
  • CS4014: Ponieważ to wywołanie nie jest oczekiwane, wykonanie bieżącej metody jest kontynuowane przed ukończeniem wywołania. Rozważ zastosowanie await operatora do wyniku wywołania.
  • CS4015: "MethodImplOptions.Synchronized" nie można zastosować do metody asynchronicznej.
  • CS4016: Ponieważ jest to metoda asynchroniczna, wyrażenie zwracane musi być typu podobnego do typu zadania, a nie typu zadeklarowanego.
  • CS4027: Typ wyrażenia nie implementuje wymaganego członka.
  • CS4028: "await" wymaga, aby typ miał odpowiednią metodę "GetAwaiter". Czy brakuje dyrektywy 'using' dla "System"?
  • CS4029: Nie można zwrócić wyrażenia typu "void".
  • CS4030: Nie można zastosować atrybutu zabezpieczeń do metody asynchronicznej.
  • CS4031: Metody asynchroniczne nie są dozwolone w atrybutach Interface, Class lub Structure, które mają atrybut "SecurityCritical" lub "SecuritySafeCritical".
  • CS4032: Operator "await" może być używany tylko w metodzie asynchronicznej. Rozważ oznaczenie tej metody modyfikatorem "async" i zmianą jego typu powrotu na "Task<T>".
  • CS4033: Operator "await" może być używany tylko w metodzie asynchronicznej. Rozważ oznaczenie tej metody modyfikatorem "async" i zmianę jego typu powrotu na "Task".
  • CS4034: Operator "await" może być używany tylko w metodzie asynchronicznej. Rozważ oznaczenie tej metody za pomocą modyfikatora "asynchronicznego".
  • CS8031: Wyrażenie lambda asynchroniczne przekonwertowane na zadanie zwracające delegata nie może zwrócić wartości.
  • CS8100: Operator "await" nie może być używany w inicjatorze zmiennej skryptu statycznego.
  • CS8177: Metody asynchroniczne nie mogą mieć lokalnych odwołań.
  • CS8178: Odwołanie zwrócone przez wywołanie metody nie może być zachowywane przez granicę "await" lub "yield".
  • CS8204: Aby typ mógł być używany jako AsyncMethodBuilder dla typu docelowego, jego właściwość Task powinna zwracać typ docelowy zamiast zadeklarowanego typu.
  • CS8403: Metoda z blokiem iteratora musi być "async", aby zwrócić IAsyncEnumerable<T>.
  • CS8411: Asynchroniczna instrukcja foreach nie może działać na zmiennych danego typu, ponieważ typ nie zawiera odpowiedniego publicznego egzemplarza ani definicji rozszerzenia dla wymaganego elementu składowego.
  • CS8892: Metoda nie będzie używana jako punkt wejścia, ponieważ znaleziono synchroniczny punkt wejścia.
  • CS8935: Atrybut AsyncMethodBuilder jest niedozwolony dla metod anonimowych bez jawnego typu zwracanego.
  • CS8940: Oczekiwano ogólnego typu zwracanego przypominającego zadanie, ale typ znaleziony w atrybucie "AsyncMethodBuilder" nie był odpowiedni. Musi to być niezwiązany typ ogólny o liczbie parametrów równej jeden, a jego typ zawierający (jeśli istnieje) nie może być typem ogólnym.
  • CS9123: Operator "&" nie powinien być używany w parametrach ani zmiennych lokalnych w metodach asynchronicznych.
  • CS9330: "MethodImplAttribute.Async" nie można zastosować ręcznie do metod. Oznacz metodę "async".

Wymagania dotyczące wyrażeń Await

  • CS1985: Nie można używać 'await' w klauzuli catch.
  • CS1986: "await" wymaga, aby typ miał odpowiednią metodę "GetAwaiter".
  • CS1992: Operator "await" może być używany tylko wtedy, gdy znajduje się w metodzie lub wyrażeniu lambda oznaczonym modyfikatorem "async".
  • CS1995: Operator "await" może być używany tylko w wyrażeniu zapytania w pierwszym wyrażeniu kolekcji początkowej klauzuli "from" lub w wyrażeniu kolekcji klauzuli "join".
  • CS1996: Nie można użyć 'await' w ciele instrukcji 'lock'.
  • CS4008: Nie można oczekiwać "void".
  • CS4032: Operator "await" może być używany tylko w metodzie asynchronicznej. Rozważ oznaczenie tej metody modyfikatorem "async" i zmianę jego typu powrotu na "Task<T>".
  • CS4033: Operator "await" może być używany tylko w metodzie asynchronicznej. Rozważ oznaczenie tej metody modyfikatorem "async" i zmianę jego typu powrotu na "Task".
  • CS4034: Operator "await" może być używany tylko w metodzie asynchronicznej. Rozważ oznaczenie tej metody za pomocą modyfikatora "asynchronicznego".
  • CS8178: Nie można zachować odwołania zwróconego przez to wywołanie w granicach "await" lub "yield".
  • CS8411: Asynchroniczna instrukcja foreach nie może działać na zmiennych typu, ponieważ typ nie zawiera odpowiedniego wystąpienia publicznego ani definicji rozszerzenia dla wymaganego elementu członkowskiego.
  • CS4001: Nie można oczekiwać na wyrażenie.
  • CS4003: "await" nie może być używany jako identyfikator w metodzie asynchronicznej lub wyrażeniu lambda.
  • CS4007: Nie można zachować wystąpienia typu w granicach "await" lub "yield".
  • CS4011: "await" wymaga, aby typ zwracany przez "GetAwaiter()" miał odpowiednimi elementami członkowskimi "IsCompleted", "OnCompleted" i "GetResult" oraz aby implementował element "INotifyCompletion" lub "ICriticalNotifyCompletion".
  • CS4027: Typ nie implementuje wymaganego członka.
  • CS4028: "await" wymaga, aby typ miał odpowiednią metodę "GetAwaiter". Czy brakuje dyrektywy using dla "System"?
  • CS8100: Operator "await" nie może być używany w inicjatorze zmiennej skryptu statycznego.

Poniższe elementy wyjaśniają, jak poprawić każdy błąd. Aby uzyskać więcej informacji na temat await operatora i wzorca awaitera, zobacz Asynchroniczne programowanie z użyciem async i await.

  • async Dodaj modyfikator do metody lub wyrażenia lambda zawierającego await wyrażenie (CS1992, CS4032, CS4033, CS4034). Kompilator wymaga modyfikatora async, aby mógł wygenerować maszynę stanów, która obsługuje asynchroniczne zawieszenie i wznowienie. Trzy warianty tego błędu oferują sugestie kontekstowe dla poprawnego typu zwracanego.
  • Przenieś await wyrażenia z bloków catch , gdy docelowy jest język C# 5 lub starszy (CS1985). Począwszy od C# 6, kompilator obsługuje await zarówno w blokach catch, jak i finally. Ten błąd nie jest już generowany w języku C# 6 lub nowszym.
  • Przenieś await wyrażenia z bloków instrukcji sterującychlock (CS1996). Asynchroniczne zawieszenie przy trzymaniu blokady ryzykuje zakleszczeniami. Blokada jest przechowywana w przełącznikach wątków, w których inny kod może czekać na tę samą blokadę.
  • Przekonstruuj wyrażenia zapytania tak, aby pojawiało się tylko w pierwszym wyrażeniu kolekcji klauzuli początkowej await lub w wyrażeniu kolekcji klauzuli from (join). Inne klauzule zapytania przekładają się na wyrażenia lambda, które nie obsługują zawieszenia asynchronicznego.
  • Zmień typ oczekiwanego wyrażenia, aby uwidocznić dostępną GetAwaiter() metodę zgodną ze wzorcem oczekiwania (CS1986, CS4028). Typ może implementować wzorzec bezpośrednio lub za pomocą metody rozszerzenia. GetAwaiter Jeśli metoda istnieje, ale brakuje using dyrektywy dla System, kompilator generuje bardziej szczegółowy komunikat CS4028 zamiast CS1986.
  • Upewnij się, że typ awaiter zwracany przez GetAwaiter() ma elementy IsCompleted, OnCompleted oraz GetResult i implementuje INotifyCompletion lub ICriticalNotifyCompletion (CS4011, CS4027). Wyrażenieawait zależy od tych składników do sprawdzania stanu ukończenia, rejestrowania kontynuacji i pobierania wyników.
  • Zmień typ zwracany metody z void na Task lub Task<TResult> tak, aby wynik mógł być oczekiwany (CS4008). Nie można oczekiwać na metodę zwracającą void, ponieważ nie ma obiektu zadania do śledzenia ukończenia lub propagacji wyjątków.
  • Zmień oczekiwane wyrażenie na typ obsługujący wzorzec awaitera (CS4001). Typy, takie jak int, string, i inne wbudowane typy, nie mają metody GetAwaiter i nie mogą być bezpośrednio oczekiwane.
  • Przechowuj wynik wywołania metody zwracanej przez ref w zmiennej lokalnej przed użyciem await (CS8178). Odwołanie zwrócone przez metodę nie może być zachowywane przez granicę await , ponieważ maszyna stanu asynchronicznego może zawiesić i wznowić działanie w innym wątku lub kontekście, unieważniając odwołanie.
  • Zaimplementować IAsyncEnumerable<T> na typie kolekcji lub dodać dostępną metodę GetAsyncEnumerator, która zwraca typ z członkami Current i MoveNextAsync (CS8411). Instrukcja await foreach wymaga , aby typ kolekcji stosował wzorzec asynchronicznej enumeracji.
  • Zmień nazwę dowolnej zmiennej lokalnej lub parametru o nazwie await wewnątrz async metody lub wyrażenia lambda (CS4003). Wewnątrz kontekstów asynchronicznych await jest kontekstowym słowem kluczowym i nie można go użyć jako identyfikatora.
  • await Przenieś wyrażenie z inicjatora zmiennej skryptu statycznego i do treści metody (CS8100). Statyczne inicjatory działają poza kontekstem asynchronizatora, więc await nie są dostępne w tej lokalizacji.
  • Zrestrukturyzuj kod tak, aby wystąpienia ref struct nie musiały być zachowywane przez granicę await lub yield (CS4007). Maszyna stanu asynchronicznego przechowuje zmienne lokalne na stercie, a ref struct typy są powiązane stosem zgodnie z projektem — nie można bezpiecznie przenieść ich do magazynu sterty między punktami zawieszenia.

Wymagania dotyczące sygnatur metod asynchronicznych

  • CS1983: Ponieważ jest to metoda asynchronizna, wyrażenie zwracane musi mieć typ "T", a nie "Task<T>".
  • CS1994: Modyfikator "async" może być używany tylko w metodach, które mają treść.
  • CS4009: Punkt wejścia zwracający void lub int nie może być asynchroniczny.
  • CS8892: Metoda nie będzie używana jako punkt wejścia, ponieważ znaleziono synchroniczny punkt wejścia.
  • CS8935: Atrybut AsyncMethodBuilder jest niedozwolony dla metod anonimowych bez jawnego typu zwracanego.
  • CS8940: Oczekiwano ogólnego typu zwracanego przypominającego zadanie, ale typ znaleziony w atrybucie "AsyncMethodBuilder" nie był odpowiedni. Musi to być niezwiązany typ ogólny arity, a jego typ zawierający (jeśli istnieje) musi być inny niż ogólny.
  • CS8403: Metoda zawierająca blok iteratora musi być "async", aby zwrócić "{1}".
  • CS9330: "MethodImplAttribute.Async" nie można zastosować ręcznie do metod. Oznacz metodę "async".
  • CS4005: Metody asynchroniczne nie mogą mieć parametrów typu wskaźnika.
  • CS4006: __arglist nie jest dozwolona na liście parametrów metod asynchronicznych.
  • CS4010: Nie można przekonwertować asynchronicznego wyrażenia lambda na typ delegata. Asynchroniczne wyrażenie lambda może zwracać void, Task lub Task<T>, z których żaden nie jest konwertowalny do typu zwracania.
  • CS4012: Nie można zadeklarować parametrów typu w metodach asynchronicznych ani asynchronicznych wyrażeniach lambda.
  • CS4015: "MethodImplOptions.Synchronized" nie można zastosować do metody asynchronicznej.
  • CS4016: Ponieważ jest to metoda asynchronizna, wyrażenie zwracane musi być typu zadania, a nie typu.
  • CS8031: Asynchroniczne wyrażenie lambda przekonwertowane na delegat zwracający zadanie nie może zwrócić wartości.
  • CS8204: Dla typu, który ma być używany jako AsyncMethodBuilder dla typu, jego właściwość Task powinna zwracać wymagany typ zamiast zadeklarowanego typu.

Poniższe elementy wyjaśniają, jak poprawić każdy błąd. Aby uzyskać więcej informacji na temat deklaracji metod asynchronicznych, zobacz async modyfikator i typy zwracane asynchroniczne.

  • Zmień wyrażenie zwracane, aby było zgodne z bazowym typem wyniku metody asynchronicznej (CS1983, CS4016). Gdy metoda asynchroniczna zwraca Task<T>, wyrażenie return musi podać wartość typu T, a nie Task<T>, ponieważ maszyna stanu wygenerowana przez kompilator opakowuje wartość w zadanie automatycznie. CS1983 pojawia się, gdy metoda zwraca Task<T>, a wyrażenie jest T; CS4016 obejmuje ogólny przypadek, w którym typ wyrażenia zwracanego nie jest zgodny.
  • async Usuń modyfikator z metod, które nie mają treści, takich jak metody abstrakcyjne lub deklaracje metod interfejsu (CS1994). Modyfikator async wymaga treści metody, aby kompilator mógł wygenerować implementację maszyny stanu.
  • Zmień typ powrotu punktu wejścia asynchronicznego na Task lub Task<TResult> (CS4009). Począwszy od C# 7.1, metoda Main może być async, ale musi zwracać Task lub Task<int> - async void, a async int nie są prawidłowymi podpisami punktów wejścia.
  • Usuń lub zmień nazwę jednego punktu wejścia, gdy projekt zawiera zarówno metodę synchroniczną, jak i asynchroniczną Main (CS8892). Kompilator wybiera synchroniczny punkt wejścia i wyświetla to ostrzeżenie dla kandydata asynchronicznego, którego ignoruje.
  • Dodaj jawny typ zwracany do wyrażenia lambda przed zastosowaniem atrybutu [AsyncMethodBuilder] (CS8935). Kompilator nie może rozpoznać typu budowniczego dla metody anonimowej, której typ zwracany jest określany na podstawie wnioskowania, ponieważ atrybut musi być zgodny z konkretnym typem zwracanym w czasie kompilacji.
  • Zmień typ określony w atrybucie [AsyncMethodBuilder] na niezwiązany typ ogólny arity, taki jak MyTaskMethodBuilder<> zamiast MyTaskMethodBuilder<T> lub typ niegeneryczny (CS8940). Typ zawierający budowniczego, jeśli istnieje, musi być również niegenericzny. Kompilator wymaga tego kształtu, aby mógł skonstruować konstruktora dla dowolnego konkretnego typu powrotu przypominającego zadanie.
  • Zastąp atrybut ręczny [MethodImpl(MethodImplOptions.Async)] słowem kluczowym w deklaracji metody (async). Flaga jest zarezerwowana MethodImplOptions.Async do użytku wewnętrznego środowiska uruchomieniowego i nie może być stosowana bezpośrednio w kodzie użytkownika.
  • async Dodaj modyfikator do metod zawierających bloki iteracyjne i zwraca IAsyncEnumerable<T> lub IAsyncEnumerator<T> (CS8403). async Bez modyfikatora kompilator traktuje metodę jako iterator synchroniczny i nie może wygenerować maszyny stanu strumienia asynchronicznego.
  • Usuń parametry typu wskaźnika z metod asynchronicznych (CS4005). Wskaźniki odwołują się do stałych lokalizacji pamięci, których nie można bezpiecznie zachować w punktach zawieszenia asynchronicznego, w których wykonywanie może zostać wznowione w innym wątku.
  • Usuń __arglist z list parametrów metody asynchronicznej (CS4006). Listy argumentów o zmiennej długości zależą od konwencji wywoływania opartych na stosie, które są niezgodne z asynchroniczną maszyną stanów alokowaną na stercie.
  • Usuń parametry ref, in lub out oraz parametry typów ref struct, takich jak Span<T> lub ReadOnlySpan<T>, z asynchronicznych metod lub wyrażeń lambda (CS4012). Te typy parametrów są powiązane ze stosem i nie można ich bezpiecznie przechwycić w stosie przydzielonym do zamknięcia maszyny stanu asynchronicznego.
  • Zmień typ delegata docelowego, aby był zgodny z typem zwracanym asynchronicznego wyrażenia lambda (CS4010). Asynchroniczne wyrażenie lambda może zwracać void, Task lub Task<TResult>, a kompilator nie może przekonwertować tych typów na dowolne typy delegatów, które oczekują różnych typów zwracanych.
  • Usuń wyrażenie return z asynchronicznej lambdy przypisanej do delegata zwracającego niegeneryczny Task lub zmień typ delegata na Func<Task<T>>, aby lambda mogła zwrócić wartość (CS8031). Niegeneryczny delegat zwracający Task reprezentuje operację asynchroniczną bez wyniku, więc zwracanie wartości powoduje niezgodność typów.
  • [MethodImpl(MethodImplOptions.Synchronized)] Usuń atrybut z metod asynchronicznych (CS4015). Opcja Synchronized uzyskuje blokadę na cały czas wykonywania metody, ale metoda asynchroniczna może zawieszać się i wznawiać pracę potencjalnie w różnych wątkach, co sprawia, że semantyka blokady staje się nieokreślona.
  • Popraw typ niestandardowy AsyncMethodBuilder , aby jego Task właściwość zwracała ten sam typ co zadeklarowany typ zwracany metody asynchronicznej (CS8204). Kompilator używa właściwości konstruktora Task do uzyskania końcowego obiektu zadania, więc niezgodność typów uniemożliwia prawidłowe działanie maszyny stanu.

Praktyki asynchroniczne

  • CS1989: Nie można przekonwertować asynchronicznych wyrażeń lambda na drzewa wyrażeń.
  • CS1991: "Typ" nie może zaimplementować zdarzenia "event", ponieważ jest to zdarzenie środowiska uruchomieniowego systemu Windows i "zdarzenie" jest zwykłym zdarzeniem platformy .NET.
  • CS1997: Ponieważ funkcja jest metodą asynchronikową, która zwraca wartość, słowo kluczowe zwracane nie może być zgodne z wyrażeniem obiektu.
  • CS1998: Ta metoda asynchroniczna nie zawiera operatorów "await" i będzie uruchamiana synchronicznie. Rozważ użycie operatora "await", aby oczekiwać na nieblokacyjne wywołania interfejsu API lub "await Task.Run(...)", aby wykonać pracę związaną z procesorem CPU w wątku w tle.
  • CS4014: Ponieważ to wywołanie nie jest oczekiwane, wykonanie bieżącej metody jest kontynuowane przed ukończeniem wywołania. Rozważ zastosowanie await operatora do wyniku wywołania.
  • CS8177: Metody asynchroniczne nie mogą mieć lokalnych odwołań.
  • CS9123: Operator "&" nie powinien być używany w parametrach ani zmiennych lokalnych w metodach asynchronicznych.
  • CS4029: Nie można zwrócić wyrażenia typu "void".
  • CS4030: Nie można zastosować atrybutu zabezpieczeń do metody asynchronicznej.
  • CS4031: Metody asynchroniczne nie są dozwolone w atrybutach Interface, Class lub Structure, które mają atrybut "SecurityCritical" lub "SecuritySafeCritical".

Poniższe elementy wyjaśniają, jak poprawić każdy błąd. Aby uzyskać więcej informacji, zobacz Asynchroniczne programowanie z użyciem async i await oraz await operator.

  • await Dodaj operator do każdego wywołania, które zwraca wartość Task lub Task<TResult>, albo jawnie zignoruj wynik za pomocą _ =, jeśli zachowanie "fire-and-forget" jest naprawdę zamierzone (CS4014). Bez await jakikolwiek wyjątek zgłoszony przez operację asynchroniczną jest dyskretnie pomijany, a metoda wywołująca kontynuuje swoje działanie przed zakończeniem operacji, co może powodować subtelne błędy w kolejności i poprawności.
  • return Usuń wyrażenie z metody asynchronicznej, której typ zwracany jest Task (niegeneryczny) lub zmień typ zwracany na Task<T> , gdy metoda musi zwrócić wartość (CS1997). W metodzie asynchronicznej, która zwraca Task, kompilator generuje opakowanie zadań — zwracanie wartości jest niezgodnością typu, ponieważ sygnatura metody nie obiecuje żadnego wyniku.
  • Dodaj co najmniej jedno await wyrażenie do treści metody lub usuń async modyfikator i zwróć zadanie bezpośrednio (CS1998). Metoda async bez żadnych await wyrażeń jest uruchamiana całkowicie synchronicznie, co powoduje dodanie niepotrzebnego obciążenia maszyny stanu. Jeśli metoda celowo opakowuje operację synchroniczną, usunięcie async i zwrócenie zadania jawnie eliminuje to obciążenie.
  • Przepisz wyrażenie lambda, aby nie używało async, podczas przypisywania do typu drzewa wyrażeń, np. Expression<Func<...>> (CS1989). Drzewa wyrażeń reprezentują kod jako struktury danych, które kompilator może analizować lub tłumaczyć, ale złożona maszyna stanu, która async generuje, nie może być przechwytywana w drzewie wyrażeń.
  • Zmień implementację zdarzeń, aby zarówno deklaracja interfejsu, jak i klasa implementowania zgadzały się, czy zdarzenie używa semantyki środowiska uruchomieniowego systemu Windows, czy zwykłych semantyki platformy .NET (CS1991). Ten błąd dotyczy scenariuszy międzyoperacyjności środowiska uruchomieniowego systemu Windows, w których nie można zaimplementować zdarzenia WinRT jako zwykłego zdarzenia platformy .NET lub odwrotnie.
  • Usuń operator address-of (&) z wyrażeń odwołujących się do parametrów lub zmiennych lokalnych wewnątrz metod asynchronicznych (CS9123). Maszyna stanu asynchronicznego może przenieść przechwycone zmienne do sterty podczas zawieszenia, co spowoduje unieważnienie każdego wskaźnika uzyskanego za pośrednictwem adresu-of.
  • Usuń zmienne lokalne przez odwołanie z metod asynchronicznych lub upewnij się, że one nie obejmują granicy await (CS8177). Maszyna stanu asynchronicznego przechwytuje zmienne lokalne w zamknięciach przydzielonych na stercie, a odwołania do lokalizacji stosu nie mogą być bezpiecznie zachowywane poza punktami zatrzymania. W C# 13 i nowszych, zmienne lokalne ref są dozwolone w metodach asynchronicznych, o ile nie obejmują granicy await, a ten błąd nie jest generowany.
  • Usuń instrukcję return zwracającą wynik z metody void, lub zmień wywołaną metodę, aby zwracała wartość (CS4029). Nie można użyć elementu return SomeVoidMethod(); , ponieważ void nie jest typem, który może zostać zwrócony jako wartość. Usuń słowo kluczowe return i wywołaj metodę jako samodzielne wywołanie lub dostosuj sygnaturę wywoływanej metody, aby zwracała konkretny typ.
  • Usuń atrybuty zabezpieczeń, takie jak [SecurityCritical] lub [SecuritySafeCritical] z metod asynchronicznych (CS4030), lub usuń async modyfikator z metod w typach oznaczonych tymi atrybutami (CS4031). Adnotacje zabezpieczeń dostępu do kodu mają zastosowanie do metody deklaratywnej, ale maszyna stanu asynchronicznego wygenerowana przez kompilator jest uruchamiana w osobnym kontekście, w którym nie można wymusić tych adnotacji zabezpieczeń.