Dela via


Lösa fel och varningar i asynkrona metoder som använder inväntningsoperatorn

Den här artikeln beskriver följande kompilatorfel:

  • CS1983: Eftersom det här är en asynkron metod måste returuttrycket vara av typen "T" i stället för "Task<T>".
  • CS1985: Det går inte att använda 'await' i en catch-sats.
  • CS1986: "await" kräver att typen har en lämplig "GetAwaiter"-metod.
  • CS1989: Async lambda-uttryck kan inte konverteras till uttrycksträd.
  • CS1991: "Typ" kan inte implementera "händelse" eftersom det är en Windows Runtime-händelse och "händelse" är en vanlig .NET-händelse.
  • CS1992: Operatorn "await" kan endast användas när den finns i en metod eller ett lambda-uttryck som har markerats med "async"-modifieraren.
  • CS1994: Modifieraren kanasync bara användas i metoder som har en brödtext.
  • CS1995: Operatorn "await" får endast användas i ett frågeuttryck i det första samlingsuttrycket för den inledandefrom satsen eller i samlingsuttrycket för en "join"-sats.
  • CS1996: Det går inte att använda 'await' inom en låssats.
  • CS1997: Eftersom funktionen är en asynkron metod som returnerar ett värde får ett returnyckelord inte följas av ett objektuttryck.
  • CS1998: Den här asynkrona metoden saknar operatorerawait och körs synkront. Överväg att använda operatorn "await" för att vänta på icke-blockerande API-anrop, eller "await Task.Run(...)" för att utföra CPU-bundet arbete på en bakgrundstråd.
  • CS4001: Det går inte att vänta på uttrycket.
  • CS4003: 'await' kan inte användas som identifierare inom en asynkron metod eller lambda-uttryck.
  • CS4005: Async-metoder kan inte ha parametrar för pekartyp.
  • CS4006: __arglist tillåts inte i parameterlistan över asynkrona metoder.
  • CS4007: Instans av typen kan inte bevaras över gränsen "await" eller "yield".
  • CS4008: Kan inte invänta 'void'.
  • CS4009: En ogiltig eller int returnerande startpunkt kan inte vara asynkron.
  • CS4010: Det går inte att konvertera asynkrona uttryck till ombudstyp. Ett asynkront uttryck kan returnera void, Task eller Task<T>, som inte kan konverteras till typ.
  • CS4011: "await" kräver att returtypen "{1}. GetAwaiter()" har lämpliga "IsCompleted", "OnCompleted" och "GetResult"-medlemmar och implementerar "INotifyCompletion" eller "ICriticalNotifyCompletion".
  • CS4012: Parametrar av typen kan inte deklareras i asynkrona metoder eller asynkrona lambda-uttryck.
  • CS4014: Eftersom det här anropet inte vänts på, fortsätter utförandet av den aktuella metoden innan anropet har slutförts. Använd gärna operatorn await på resultatet av anropet.
  • CS4015: "MethodImplOptions.Syncd" kan inte tillämpas på en asynkron metod.
  • CS4016: Eftersom det här är en asynkron metod, måste returuttrycket vara av typen Task eller liknande istället för den deklarerade typen.
  • CS4027: Uttryckstypen implementerar inte nödvändig medlem.
  • CS4028: "await" kräver att typen har en lämplig "GetAwaiter"-metod. Saknar du ett användningsdirektiv för "System"?
  • CS4029: Det går inte att returnera ett uttryck av typen "void".
  • CS4030: Säkerhetsattributet kan inte tillämpas på en Async-metod.
  • CS4031: Asynkrona metoder tillåts inte i ett gränssnitt, en klass eller en struktur som har attributet SecurityCritical eller SecuritySafeCritical.
  • CS4032: Operatorn 'await' kan endast användas inom en asynkron metod. Överväg att markera den här metoden med modifieraren "async" och ändra dess returtyp till "Task<T>".
  • CS4033: Operatorn 'await' kan endast användas inom en asynkron metod. Överväg att markera den här metoden med modifierarenasync och ändra dess returtyp till .Task
  • CS4034: Operatorn 'await' kan endast användas inom en asynkron metod. Överväg att markera den här metoden med modifieraren "async".
  • CS8031: Async lambda-uttryck som konverterats till en delegering som returnerar en uppgift kan inte returnera ett värde.
  • CS8100: Operatorn 'await' kan inte användas i en variabelinitierare för statiska skript.
  • CS8177: Asynkrona metoder kan inte ha lokala efterreferenser.
  • CS8178: En referens som returneras av ett anrop till metoden kan inte bevaras över gränsen "await" eller "yield".
  • CS8204: För typ som ska användas som AsyncMethodBuilder för typmål bör dess uppgiftsegenskap returnera måltyp i stället för deklarerad typ.
  • CS8403: Metoden med ett iteratorblock måste vara "async" för att returnera IAsyncEnumerable<T>.
  • CS8411: Asynkron foreach-instruktion kan inte användas på variabler av typen eftersom typen inte innehåller en lämplig offentlig instans eller tilläggsdefinition för obligatorisk medlem.
  • CS8892: Metoden används inte som startpunkt eftersom en synkron startpunkt hittades.
  • CS8935: Attributet AsyncMethodBuilder tillåts inte för anonyma metoder utan en explicit returtyp.
  • CS8940: En generisk, uppgiftsliknande returtyp förväntades, men den typ som hittades i attributet "AsyncMethodBuilder" var inte lämplig. Det måste vara en obunden generisk typ med aritet ett, och den omgivande typen (om någon) måste vara icke-generisk.
  • CS9123: Operatorn '&' ska inte användas på parametrar eller lokala variabler i asynkrona metoder.
  • CS9330: 'MethodImplAttribute.Async' kan inte tillämpas manuellt på metoder. Markera metoden "async".

Krav för Await-uttryck

  • CS1985: Det går inte att använda await i en catch-sats.
  • CS1986: "await" kräver att typen har en lämplig "GetAwaiter"-metod.
  • CS1992: Operatorn "await" kan endast användas när den finns i en metod eller ett lambda-uttryck som har markerats med modifieraren .async
  • CS1995: Operatorn "await" får endast användas i ett frågeuttryck i det första samlingsuttrycket för den inledandefrom satsen eller i samlingsuttrycket för en "join"-sats.
  • CS1996: Det går inte att använda await i en lock-sats.
  • CS4008: Kan inte invänta 'void'.
  • CS4032: Operatorn 'await' kan endast användas inom en asynkron metod. Överväg att markera den här metoden med modifierarenasync och ändra dess returtyp till .Task<T>
  • CS4033: Operatorn 'await' kan endast användas inom en asynkron metod. Överväg att markera den här metoden med modifierarenasync och ändra dess returtyp till .Task
  • CS4034: Operatorn 'await' kan endast användas inom en asynkron metod. Överväg att markera den här metoden med modifieraren "async".
  • CS8178: En referens som returneras av det här anropet kan inte bevaras över gränsen "await" eller "yield".
  • CS8411: Asynkron foreach-instruktion kan inte användas på variabler av typen eftersom typen inte innehåller en lämplig offentlig instans eller tilläggsdefinition för obligatorisk medlem.
  • CS4001: Kan inte vänta in uttryck.
  • CS4003: 'await' kan inte användas som identifierare inom en asynkron metod eller lambda-uttryck.
  • CS4007: Instans av typen kan inte bevaras över gränsen "await" eller "yield".
  • CS4011: "await" kräver att returtypen "GetAwaiter()" har lämpliga "IsCompleted", "OnCompleted" och "GetResult"-medlemmar och implementerar "INotifyCompletion" eller "ICriticalNotifyCompletion".
  • CS4027: Typen implementerar inte nödvändig medlem.
  • CS4028: "await" kräver att typen har en lämplig "GetAwaiter"-metod. Saknar du ett användningsdirektiv för "System"?
  • CS8100: Operatorn 'await' kan inte användas i en variabelinitierare för statiska skript.

Följande objekt förklarar hur du korrigerar varje fel. Mer information om operatornawait och maktvänt-mönstret finns i Asynkron programmering med async och await.

  • async Lägg till modifieraren i metoden eller lambda-uttrycket som innehåller await uttrycket (CS1992, CS4032, CS4033, CS4034). Kompilatorn kräver async modifieraren så att den kan generera tillståndsmaskinen som hanterar asynkron suspendering och återupptagning. De tre varianterna av det här felet ger sammanhangsspecifika förslag på rätt returtyp.
  • Flytta await uttryck ut ur catch block när du arbetar med C# 5 eller tidigare (CS1985). Från och med C# 6 stöder kompilatorn await i både catch och finally block. Det här felet skapas inte längre i C# 6 och senare.
  • Flytta await uttryck från instruktionsblocklock (CS1996). Asynkron fjädring vid låsning riskerar dödlägen. Låset hålls över trådväxlar där annan kod kanske väntar på samma lås.
  • Omstrukturera frågeuttryck så att de await endast visas i det första samlingsuttrycket för den inledande from satsen eller i samlingsuttrycket för en join sats (CS1995). Andra frågesatser översätts till lambda-uttryck som inte stöder asynkron suspendering.
  • Ändra det inväntade uttryckets typ så att det exponerar en tillgänglig GetAwaiter() metod som följer awaiter-mönstret (CS1986, CS4028). Typen kan implementera mönstret direkt eller via en tilläggsmetod. GetAwaiter Om metoden finns men du saknar ett using direktiv för System, kommer kompilatorn att skapa det mer specifika CS4028-meddelandet istället för CS1986.
  • Kontrollera att den inväntartyp som returneras av GetAwaiter() har IsCompleted, OnCompletedoch GetResult medlemmar och implementerar INotifyCompletion eller ICriticalNotifyCompletion (CS4011, CS4027). Uttrycketawait är beroende av dessa medlemmar för att kontrollera slutförandestatus, registrera fortsättningar och hämta resultat.
  • Ändra den anropade metodens returtyp från void till Task eller Task<TResult> så kan resultatet inväntas (CS4008). Du kan inte invänta en void-returning-metod eftersom det inte finns något aktivitetsobjekt för att spåra slutförande eller sprida undantag.
  • Ändra det väntade uttrycket till en typ som stöder awaiter-mönstret (CS4001). Typer som int, string och andra inbyggda typer har ingen GetAwaiter-metod och kan inte inväntas direkt.
  • Lagra resultatet av ett referensreturmetodanrop i en lokal variabel innan du använder await (CS8178). En referens som returneras av en metod kan inte bevaras över en await gräns eftersom asynkron tillståndsdatorn kan pausa och återupptas i en annan tråd eller kontext, vilket gör referensen ogiltig.
  • Implementera IAsyncEnumerable<T> på samlingstypen eller lägg till en tillgänglig GetAsyncEnumerator metod som returnerar en typ med Current och MoveNextAsync medlemmar (CS8411). Instruktionenawait foreach kräver att samlingstypen följer det asynkrona uppräkningsbara mönstret.
  • Byt namn på en lokal variabel eller parameter med namnet await i en async metod eller lambda-uttryck (CS4003). I asynkrona kontexter await är ett kontextuellt nyckelord och kan inte användas som identifierare.
  • await Flytta uttrycket från den statiska skriptvariabelinitieraren och till en metodtext (CS8100). Statiska initierare körs utanför en asynkron kontext, så await är inte tillgänglig på den platsen.
  • Omstrukturera koden så att ref struct-instanser inte behöver bevaras över en await- eller yield-gräns (CS4007). Asynkron tillståndsmaskin lagrar lokala variabler i heap-minnet, och ref struct typerna är stackbundna av design – de kan inte flyttas på ett säkert sätt till heaplagring över pauspunkter.

Krav för asynkron metodsignatur

  • CS1983: Eftersom det här är en asynkron metod måste returuttrycket vara av typen "T" i stället för "Task<T>".
  • CS1994: Modifieraren kanasync bara användas i metoder som har en brödtext.
  • CS4009: En ogiltig eller int returnerande startpunkt kan inte vara asynkron.
  • CS8892: Metoden används inte som startpunkt eftersom en synkron startpunkt hittades.
  • CS8935: Attributet AsyncMethodBuilder tillåts inte för anonyma metoder utan en explicit returtyp.
  • CS8940: En allmän uppgiftsliknande returtyp förväntades, men den typ som hittades i attributet "AsyncMethodBuilder" var inte lämplig. Det måste vara en obunden generisk typ av aritet ett, och dess eventuella innehållande typ måste vara icke-generisk.
  • CS8403: Metoden med ett iteratorblock måste vara 'async' för att returnera '{1}'.
  • CS9330: 'MethodImplAttribute.Async' kan inte tillämpas manuellt på metoder. Markera metoden .async
  • CS4005: Async-metoder kan inte ha parametrar för pekartyp.
  • CS4006: __arglist tillåts inte i parameterlistan över asynkrona metoder.
  • CS4010: Det går inte att konvertera asynkron lambda till delegeringstypen. En asynkron lambda kan returnera void, Task eller Task<T>, vilka inte kan konverteras till returtypen.
  • CS4012: Parametrar av typen kan inte deklareras i asynkrona metoder eller asynkrona lambda-uttryck.
  • CS4015: "MethodImplOptions.Syncd" kan inte tillämpas på en asynkron metod.
  • CS4016: Eftersom det här är en asynkron metod måste returuttrycket vara av aktivitetstyp i stället för typ.
  • CS8031: Async lambda-uttryck som har konverterats till en delegering som returnerar en uppgift kan inte returnera ett värde.
  • CS8204: För typ som ska användas som AsyncMethodBuilder för typ bör dess aktivitetsegenskap returnera den typ som krävs i stället för deklarerad typ.

Följande objekt förklarar hur du korrigerar varje fel. Mer information om asynkrona metoddeklarationer finns i async modifieraren och Async-returtyperna.

  • Ändra returuttrycket så att det matchar asynkronmetodens underliggande resultattyp (CS1983, CS4016). När en asynkron metod returnerar Task<T>måste -instruktionen return ange ett värde av typen T, inte Task<T>, eftersom den kompilatorgenererade tillståndsdatorn omsluter värdet i en aktivitet automatiskt. CS1983 visas när metoden returnerar Task<T> och uttrycket är T; CS4016 omfattar det allmänna fallet där returuttryckstypen inte matchar.
  • async Ta bort modifieraren från metoder som inte har någon brödtext, till exempel abstrakta metoder eller gränssnittsmetoddeklarationer (CS1994). Modifieraren async kräver en metodtext så att kompilatorn kan generera tillståndsdatorimplementeringen.
  • Ändra en asynkron startpunkts returtyp till Task eller Task<TResult> (CS4009). Från och med C# 7.1 kan metoden vara , men den måste returnera eller , och är inte giltiga signaturer för startpunkten.
  • Ta bort eller byt namn på en startpunkt när projektet innehåller både en synkron och en asynkron Main metod (CS8892). Kompilatorn väljer den synkrona startpunkten och utfärdar den här varningen för den asynkrona kandidat som ignoreras.
  • Lägg till en explicit returtyp i lambda-uttrycket innan du tillämpar [AsyncMethodBuilder] attributet (CS8935). Kompilatorn kan inte matcha builder-typen för en anonym metod vars returtyp härleds, eftersom attributet måste matchas med en specifik returtyp vid kompileringstillfället.
  • Ändra den typ som anges i [AsyncMethodBuilder]-attributet till en obunden generisk typ av aritet ett, till exempel MyTaskMethodBuilder<> i stället för MyTaskMethodBuilder<T> eller en icke-generisk typ (CS8940). Byggarens innehållande typ, om någon, måste också vara icke-generisk. Kompilatorn kräver den här formen så att den kan konstruera byggaren för alla konkreta uppgiftsliknande returtyper.
  • Ersätt det manuella [MethodImpl(MethodImplOptions.Async)] attributet med nyckelordet async i metoddeklarationen (CS9330). Flaggan MethodImplOptions.Async är reserverad för intern användning vid körning och kan inte användas direkt i användarkoden.
  • Lägg till modifieraren i async metoder som innehåller iteratorblock och returnerar IAsyncEnumerable<T> eller IAsyncEnumerator<T> (CS8403). async Utan modifieraren behandlar kompilatorn metoden som en synkron iterator och kan inte generera asynkron strömtillståndsdator.
  • Ta bort parametrar av pekartyp från asynkrona metoder (CS4005). Pekare hänvisar till fasta minnesplatser som inte på ett säkert sätt kan bevaras över asynkrona avbrott där körningen kan fortsätta på en annan tråd.
  • Ta bort __arglist från asynkrona metodparameterlistor (CS4006). Argumentlistor med variabel längd beror på stackbaserade anropskonventioner som inte är kompatibla med den heapallokerade asynkrona tillståndsdatorn.
  • Ta bort ref, in, eller out parametrar och parametrar för ref struct typer som Span<T> eller ReadOnlySpan<T>, från asynkrona metoder eller asynkrona lambda-uttryck (CS4012). Dessa parametertyper är stackbundna och kan inte fångas in på ett säkert sätt i den heap-allokerade asynkron tillståndsmaskin-stängningen.
  • Ändra måldelegattypen så att den matchar asynkron lambdas returtyp (CS4010). En asynkron lambda kan returnera void, Taskeller Task<TResult>och kompilatorn kan inte konvertera dessa till godtyckliga delegattyper som förväntar sig olika returtyper.
  • Ta bort return uttrycket från en asynkron lambda som är tilldelad till en icke-generisk delegerad med Task-returtyp, eller ändra delegeringstypen till Func<Task<T>> så att lambda kan returnera ett värde (CS8031). Ett icke-generiskt Task-returnerande delegat representerar en asynkron åtgärd utan resultat, så att returnera ett värde är en typkonflikt.
  • [MethodImpl(MethodImplOptions.Synchronized)] Ta bort attributet från asynkrona metoder (CS4015). Alternativet Synchronized hämtar ett lås för hela metodkörningen, men en asynkron metod pausar och återupptar potentiellt på olika trådar, vilket gör låssemantiken odefinierad.
  • Korrigera den anpassade AsyncMethodBuilder typen så att dess Task egenskap returnerar samma typ som async-metodens deklarerade returtyp (CS8204). Kompilatorn använder byggarens Task egenskap för att hämta det slutliga aktivitetsobjektet, så ett typmatchningsfel hindrar tillståndsmaskinen från att fungera korrekt.

Asynkrona metoder

  • CS1989: Async lambda-uttryck kan inte konverteras till uttrycksträd.
  • CS1991: "Typ" kan inte implementera "händelse" eftersom det är en Windows Runtime-händelse och "händelse" är en vanlig .NET-händelse.
  • CS1997: Eftersom funktionen är en asynkron metod som returnerar ett värde får ett returnyckelord inte följas av ett objektuttryck.
  • CS1998: Den här asynkrona metoden saknar operatorerawait och körs synkront. Överväg att använda operatorn "await" för att vänta på icke-blockerande API-anrop, eller "await Task.Run(...)" för att utföra CPU-bundet arbete på en bakgrundstråd.
  • CS4014: Eftersom det här anropet inte väntas in, fortsätter den aktuella metoden utan att vänta på att anropet ska slutföras. Överväg att tillämpa operatorn await på resultatet av anropet.
  • CS8177: Asynkrona metoder kan inte ha lokala efterreferenser.
  • CS9123: Operatorn '&' ska inte användas på parametrar eller lokala variabler i asynkrona metoder.
  • CS4029: Det går inte att returnera ett uttryck av typen "void".
  • CS4030: Säkerhetsattributet kan inte tillämpas på en Async-metod.
  • CS4031: Asynkrona metoder tillåts inte i ett gränssnitt, en klass eller en struktur som har attributet SecurityCritical eller SecuritySafeCritical.

Följande objekt förklarar hur du korrigerar varje fel. För mer information, se Asynkron programmering med async och await och await operatorn.

  • Lägg till operatorn await i varje anrop som returnerar Task eller Task<TResult>eller uttryckligen tar bort resultatet med _ = om beteendet fire-and-forget verkligen är avsett (CS4014). Utan awaitgår alla undantag som utlöses av den asynkrona åtgärden i tysthet förlorade och anropsmetoden fortsätter att köras innan åtgärden är klar, vilket kan orsaka diskreta ordningsföljder och korrekthetsfel.
  • return Ta bort uttrycket från en asynkron metod vars returtyp är Task (icke-generisk) eller ändra returtypen till Task<T> när metoden behöver returnera ett värde (CS1997). I en asynkron metod som returnerar Taskgenererar kompilatorn aktivitetsomslutningen – att returnera ett värde är en typmatchningsfel eftersom metodsignaturen inte lovar något resultat.
  • Lägg till minst ett await uttryck i metodtexten eller ta bort async modifieraren och returnera uppgiften direkt (CS1998). En async metod utan await uttryck körs helt synkront, vilket ger onödig överbelastning för tillståndsmaskinen. Om metoden avsiktligt omsluter en synkron åtgärd, kan du eliminera överkostnaden genom att ta bort async och uttryckligen återvända uppgiften.
  • Skriv om lambda-uttrycket så att det inte används async när det tilldelas till en uttrycksträdstyp som Expression<Func<...>> (CS1989). Uttrycksträd representerar kod som datastrukturer som kompilatorn kan analysera eller översätta, men den komplexa tillståndsdatorn som async producerar kan inte samlas in i ett uttrycksträd.
  • Ändra händelseimplementeringen så att både gränssnittsdeklarationen och implementeringsklassen är överens om huruvida händelsen använder Windows Runtime-semantik eller vanlig .NET-semantik (CS1991). Det här felet gäller för Windows Runtime-interopscenarier där en WinRT-händelse inte kan implementeras som en vanlig .NET-händelse eller vice versa.
  • Ta bort operatorns adress (&) från uttryck som refererar till parametrar eller lokala variabler i asynkrona metoder (CS9123). Asynkron tillståndsmaskin kan flytta insamlade variabler till minneshög under processen att avbryta, vilket skulle göra ogiltigt alla pekare som erhålls genom användning av en adressoperator.
  • Ta bort lokala variabler med referens från asynkrona metoder eller se till att de inte sträcker sig över en await gräns (CS8177). Asynkron tillståndsdatorn samlar in lokala variabler i heapallokerade stängningar, och referenser till stackplatser kan inte bevaras på ett säkert sätt mellan upphängningspunkter. I C# 13 och senare tillåts lokala variabler i asynkrona metoder, så länge de inte korsar en gräns, och detta fel inte genereras.
  • Ta bort -instruktionen return som returnerar resultatet av en void-returning-metod eller ändra den anropade metoden för att returnera ett värde (CS4029). Du kan inte använda return SomeVoidMethod(); eftersom void det inte är en typ som kan returneras som ett värde. Ta antingen bort nyckelordet return och anropa metoden som en fristående instruktion eller ändra den anropade metodens signatur för att returnera en konkret typ.
  • Ta bort säkerhetsattribut som [SecurityCritical] eller [SecuritySafeCritical] från asynkrona metoder (CS4030) eller ta bort async modifieraren från metoder i typer som har markerats med dessa attribut (CS4031). Säkerhetsanteckningarna för kodåtkomst gäller för deklareringsmetoden, men den kompilatorgenererade asynkrona tillståndsdatorn körs i en separat kontext där dessa säkerhetsanteckningar inte kan tillämpas.