Freigeben über


Beheben von Fehlern und Warnungen in asynchronen Methoden mithilfe des Await-Operators

In diesem Artikel werden die folgenden Compilerfehler behandelt:

  • CS1983: Da es sich um eine asynchrone Methode handelt, muss der Rückgabeausdruck vom Typ 'Task<T>' statt 'T' sein.
  • CS1985: In einer Catch-Klausel kann nicht gewartet werden.
  • CS1986: 'await' erfordert, dass der Typ über eine geeignete 'GetAwaiter' Methode verfügt.
  • CS1989: Async Lambda-Ausdrücke können nicht in Ausdrucksbäume konvertiert werden.
  • CS1991: "Type" kann "event" nicht implementieren, da es sich um ein Windows-Runtime-Ereignis handelt und "event" ein reguläres .NET-Ereignis ist.
  • CS1992: Der Operator 'await' kann nur verwendet werden, wenn er in einer Methode oder einem Lambda-Ausdruck enthalten ist, der mit dem Modifizierer "asynchron" gekennzeichnet ist.
  • CS1994: Der Modifizierer "async" kann nur in Methoden verwendet werden, die über einen Textkörper verfügen.
  • CS1995: Der Operator 'await' darf nur in einem Abfrageausdruck innerhalb des ersten Sammlungsausdrucks der anfänglichen 'from' Klausel oder innerhalb des Sammlungsausdrucks einer 'join' Klausel verwendet werden.
  • CS1996: Im Textkörper einer Lock-Anweisung kann nicht gewartet werden.
  • CS1997: Da es sich bei der Funktion um eine asynchrone Methode handelt, die einen Wert zurückgibt, darf auf ein Rückgabeschlüsselwort kein Objektausdruck folgen.
  • CS1998: Diese asynchrone Methode enthält keine 'await' Operatoren und wird synchron ausgeführt. Erwägen Sie die Verwendung des Operators "await", um nicht blockierende API-Aufrufe zu erwarten, oder "await Task.Run(...)", um CPU-gebundene Arbeit in einem Hintergrundthread auszuführen.
  • CS4008: Es kann nicht auf 'void' gewartet werden.
  • CS4009: Ein leerer oder int-Rückgabepunkt kann nicht asynchron sein.
  • CS4014: Da dieser Aufruf nicht erwartet wird, wird die Ausführung der aktuellen Methode fortgesetzt, bevor der Aufruf abgeschlossen ist. Erwägen Sie, den await Operator auf das Ergebnis des Anrufs anzuwenden.
  • CS4032: Der Operator 'await' kann nur innerhalb einer asynchronen Methode verwendet werden. Erwägen Sie, diese Methode mit dem Modifizierer "asynchron" zu markieren und den Rückgabetyp in "Task<T>" zu ändern.
  • CS4033: Der Operator 'await' kann nur innerhalb einer asynchronen Methode verwendet werden. Erwägen Sie, diese Methode mit dem Modifizierer "async" zu markieren und den Rückgabetyp in "Task" zu ändern.
  • CS8892: Die Methode wird nicht als Einstiegspunkt verwendet, da ein synchroner Einstiegspunkt gefunden wurde.
  • CS9123: Der Operator "&" sollte nicht für Parameter oder lokale Variablen in asynchronen Methoden verwendet werden.
  • CS9330: 'MethodImplAttribute.Async' kann nicht manuell auf Methoden angewendet werden. Markieren Sie die Methode "async".

Anforderungen für den Await-Ausdruck

  • CS1985: In einer Catch-Klausel kann nicht gewartet werden.
  • CS1986: 'await' erfordert, dass der Typ über eine geeignete 'GetAwaiter' Methode verfügt.
  • CS1992: Der Operator "await" kann nur verwendet werden, wenn er in einer Methode oder einem Lambda-Ausdruck enthalten ist, der mit dem Modifizierer "async" gekennzeichnet ist.
  • CS1995: Der Operator 'await' darf nur in einem Abfrageausdruck innerhalb des ersten Sammlungsausdrucks der anfänglichen 'from' Klausel oder innerhalb des Sammlungsausdrucks einer 'join' Klausel verwendet werden.
  • CS1996: Im Textkörper einer Lock-Anweisung kann nicht gewartet werden.
  • CS4008: Es kann nicht auf 'void' gewartet werden.
  • CS4032: Der Operator 'await' kann nur innerhalb einer asynchronen Methode verwendet werden. Erwägen Sie, diese Methode mit dem Modifizierer "async" zu markieren und den Rückgabetyp in "Task<T>" zu ändern.
  • CS4033: Der Operator 'await' kann nur innerhalb einer asynchronen Methode verwendet werden. Erwägen Sie, diese Methode mit dem Modifizierer "async" zu markieren und den Rückgabetyp in "Task" zu ändern.

Um den await Operator richtig zu verwenden, befolgen Sie diese Regeln. Weitere Informationen finden Sie unter Asynchrone Programmierung mit async und await.

  • Verwenden Sie await nicht in Catch-Klauseln (CS1985). Während Sie await in Try-Blöcken und "finally-Blöcken" (in C# 6 und höher) verwenden können, stellen Catch-Blöcke besondere Herausforderungen bei der Ausnahmebehandlung und beim Steuerungsfluss dar.
  • Verwenden Sie await nicht innerhalb lock Anweisungsblöcken (CS1996). Der Compiler unterstützt dies nicht, um Code zu vermeiden, der für Deadlocks anfällig ist.
  • Verwenden Sie await nur an bestimmten Stellen innerhalb von Abfrageausdrücken (CS1995): innerhalb des ersten Auflistungsausdrucks der anfänglichen from Klausel oder innerhalb des Auflistungsausdrucks einer join Klausel.
  • Markieren Sie Methoden oder Lambda-Ausdrücke mit dem async-Modifizierer, bevor Sie await verwenden (CS1992, CS4032, CS4033).
  • Stellen Sie sicher, dass await-Typen eine zugängliche GetAwaiter Methode haben, die einen Awaiter-Typ (CS1986) zurückgibt.
  • Wenden Sie await nicht auf Ausdrücke vom Typ void an (CS4008).
  • Ändern Sie den Rückgabetyp Task für Methoden, die keinen Wert zurückgeben, oder Task<T> für Methoden, die einen Wert zurückgeben.

Async-Methodensignaturanforderungen

  • CS1983: Da es sich um eine asynchrone Methode handelt, muss der Rückgabeausdruck vom Typ 'Task<T>' statt 'T' sein.
  • CS1994: Der Modifizierer "async" kann nur in Methoden verwendet werden, die über einen Textkörper verfügen.
  • CS4009: Ein leerer oder int-Rückgabepunkt kann nicht asynchron sein.
  • CS8892: Die Methode wird nicht als Einstiegspunkt verwendet, da ein synchroner Einstiegspunkt gefunden wurde.
  • CS9330: 'MethodImplAttribute.Async' kann nicht manuell auf Methoden angewendet werden. Markieren Sie die Methode "async".

Um asynchrone Methoden ordnungsgemäß zu deklarieren, befolgen Sie diese Signaturanforderungen. Weitere Informationen finden Sie unter Async-Hauptrücklaufwerte.

  • Gibt einen der gültigen Typen zurück: void, Task, Task<T>, einen vorgangsähnlichen Typ, IAsyncEnumerable<T>, oder IAsyncEnumerator<T> (CS1983).
  • Verwenden Sie den async Modifizierer nur für Methoden mit einem Textkörper (CS1994). Entfernen Sie den async Modifizierer für abstrakte Methoden in Schnittstellen oder Klassen.
  • Aktualisieren Sie auf C# 7.1 oder höher, um async am Einstiegspunkt Main zu verwenden, oder vermeiden Sie die Verwendung von async an Einstiegspunkten in früheren Versionen (CS4009).
  • Entfernen Sie synchrone Einstiegspunkte, wenn Sowohl Synchronisierungs- als auch asynchrone Einstiegspunkte (CS8892) vorhanden sind.
  • Verwenden Sie das async Schlüsselwort anstelle manueller Anwendung von MethodImplAttribute.Async (CS9330).

Asynchrone Praktiken

  • CS1989: Async Lambda-Ausdrücke können nicht in Ausdrucksbäume konvertiert werden.
  • CS1991: "Type" kann "event" nicht implementieren, da es sich um ein Windows-Runtime-Ereignis handelt und "event" ein reguläres .NET-Ereignis ist.
  • CS1997: Da es sich bei der Funktion um eine asynchrone Methode handelt, die einen Wert zurückgibt, darf auf ein Rückgabeschlüsselwort kein Objektausdruck folgen.
  • CS1998: Diese asynchrone Methode enthält keine 'await' Operatoren und wird synchron ausgeführt. Erwägen Sie die Verwendung des Operators "await", um nicht blockierende API-Aufrufe zu erwarten, oder "await Task.Run(...)", um CPU-gebundene Arbeit in einem Hintergrundthread auszuführen.
  • CS4014: Da dieser Aufruf nicht erwartet wird, wird die Ausführung der aktuellen Methode fortgesetzt, bevor der Aufruf abgeschlossen ist. Erwägen Sie, den await Operator auf das Ergebnis des Anrufs anzuwenden.
  • CS9123: Der Operator "&" sollte nicht für Parameter oder lokale Variablen in asynchronen Methoden verwendet werden.

Befolgen Sie die folgenden bewährten Methoden, um asynchronen Code ordnungsgemäß zu schreiben und häufige Fallstricke zu vermeiden. Weitere Informationen finden Sie unter Asynchrone Programmierung mit async und await.

  • Warten Sie immer auf Aufrufe von asynchronen Methoden, die zurückgeben Task oder Task<TResult> (CS4014). Nicht erwartete Anrufe können zu verlorenen Ausnahmen und unerwartetem Verhalten führen.
  • Geben Sie keinen Wert aus asynchronen Methoden zurück, die Task zurückgeben (nicht generisch); verwenden Sie stattdessen Task<T> (CS1997).
  • Schließen Sie mindestens einen await Operator in asynchrone Methoden ein, oder entfernen Sie den async Modifizierer (CS1998).
  • Entfernen Sie die return Anweisung, wenn die Methode zurückgegeben Task werden soll (CS1997, CS1998).
  • Ändern Sie den Rückgabetyp der Methode so, dass Task<T> ein Wert zurückgegeben wird (CS1997, CS1998).
  • Entfernen Sie den async Modifizierer, und geben Sie die Aufgabe direkt zurück, wenn Sie den asynchronen Zustandscomputer (CS1997, CS1998) nicht benötigen.
  • Verwenden Sie keine asynchronen Methoden in Ausdrucksbäumen (CS1989). Ausdrucksstrukturen stellen Code als Daten dar und unterstützen nicht die komplexen Zustandsautomattransformationen, die von asynchronen Methoden benötigt werden.
  • Markieren Sie keine Accessoren zum Hinzufügen oder Entfernen in einer Schnittstelle oder einem WinRT-Ereignis als asynchron (CS1991). Dies ist eine plattformspezifische Einschränkung für die Interoperabilität von Windows-Runtime.
  • Vermeiden Sie die Verwendung der Adresse des Operators (&) für Ausdrücke in asynchronen Methoden (CS9123). Das Ziel kann während des Anhaltens im Arbeitsspeicher verschoben werden, wodurch der Zeiger ungültig wird.