Dela via


Kompilatorvarning (nivå 1) CS4014

Eftersom det här anropet inte väntar fortsätter körningen av den aktuella metoden innan anropet har slutförts. Överväg att tillämpa operatorn await på resultatet av anropet.

Den aktuella metoden anropar en asynkron metod som returnerar en Task eller en Task<TResult> och som inte tillämpar inväntningsoperatorn på resultatet. Anropet till asynkron metod startar en asynkron uppgift. Men eftersom ingen await operator tillämpas fortsätter programmet utan att vänta på att aktiviteten ska slutföras. I de flesta fall är det beteendet inte vad du förväntar dig. Vanligtvis beror andra aspekter av anropsmetoden på resultatet av anropet eller, minimalt, den anropade metoden förväntas slutföras innan du återvänder från metoden som innehåller anropet.

Ett lika viktigt problem är vad som händer med undantag som genereras i den så kallade async-metoden. Ett undantag som genereras i en metod som returnerar en Task eller Task<TResult> lagras i den returnerade aktiviteten. Om du inte väntar på uppgiften eller uttryckligen söker efter undantag går undantaget förlorat. Om du väntar på uppgiften är dess undantag återväxt.

Som bästa praxis bör du alltid invänta samtalet.

Du bör endast överväga att ignorera varningen om du är säker på att du inte vill vänta tills det asynkrona anropet har slutförts och att den anropade metoden inte genererar några undantag. I så fall kan du ignorera varningen genom att tilldela aktivitetsresultatet för anropet till en variabel.

I följande exempel visas hur du orsakar varningen, hur du undertrycker den och hur du väntar på anropet.

static async Task CallingMethodAsync(int millisecondsDelay)
{
    Console.WriteLine("  Entering calling method.");

    // Call #1.
    // Call an async method. Because you don't await it, its completion
    // isn't coordinated with the current method, CallingMethodAsync.
    // The following line causes warning CS4014.
    CalledMethodAsync(millisecondsDelay);

    // Call #2.
    // To suppress the warning without awaiting, you can assign the
    // returned task to a variable. The assignment doesn't change how
    // the program runs. However, recommended practice is always to
    // await a call to an async method.

    // Replace Call #1 with the following line.
    // Task delayTask = CalledMethodAsync(millisecondsDelay);

    // Call #3
    // To contrast with an awaited call, replace the unawaited call
    // (Call #1 or Call #2) with the following awaited call. Best
    // practice is to await the call.

    // await CalledMethodAsync(millisecondsDelay);

    Console.WriteLine("  Returning from calling method.");
}

static async Task CalledMethodAsync(int millisecondsDelay)
{
    Console.WriteLine("    Entering called method, starting and awaiting Task.Delay.");

    await Task.Delay(millisecondsDelay);

    Console.WriteLine("    Task.Delay is finished--returning from called method.");
}

I exemplet, om du väljer Ring #1 eller Samtal #2, avslutas den asynkrona asynkrona metoden CalledMethodAsync efter att både anroparen CallingMethodAsync och anroparens anropare har slutförts. Den sista raden i följande utdata visar dig när den anropade metoden är klar. Post till och avsluta från händelsehanteraren som anropar CallingMethodAsync i det fullständiga exemplet markeras i utdata.

Entering the Click event handler.
  Entering calling method.
    Entering called method, starting and awaiting Task.Delay.
  Returning from calling method.
Exiting the Click event handler.
    Task.Delay is finished--returning from called method.

Du kan också förhindra kompilatorvarningar med hjälp av #pragma varningsdirektiv .

Exempel

Följande konsolprogram innehåller metoderna från föregående exempel. Följande steg konfigurerar programmet.

  1. Skapa ett konsolprogram och ge det AsyncWarningnamnet .

  2. I Visual Studio Code-redigeraren väljer du filen Program.cs .

  3. Ersätt koden i Program.cs med följande kod.

    using System;
    using System.Threading.Tasks;
    
    namespace AsyncWarning
    {
        class Program
        {
            static async Task Main()
            {
                Console.WriteLine("Entering Main() application entry point.");
    
                int millisecondsDelay = 2000;
                await CallingMethodAsync(millisecondsDelay);
    
                Console.WriteLine("Exiting Main() application entry point.");
    
                await Task.Delay(millisecondsDelay + 500);
            }
    
            static async Task CallingMethodAsync(int millisecondsDelay)
            {
                Console.WriteLine("  Entering calling method.");
    
                // Call #1.
                // Call an async method. Because you don't await it, its completion
                // isn't coordinated with the current method, CallingMethodAsync.
                // The following line causes warning CS4014.
                // CalledMethodAsync(millisecondsDelay);
    
                // Call #2.
                // To suppress the warning without awaiting, you can assign the
                // returned task to a variable. The assignment doesn't change how
                // the program runs. However, recommended practice is always to
                // await a call to an async method.
    
                // Replace Call #1 with the following line.
                //Task delayTask = CalledMethodAsync(millisecondsDelay);
    
                // Call #3
                // To contrast with an awaited call, replace the unawaited call
                // (Call #1 or Call #2) with the following awaited call. Best
                // practice is to await the call.
    
                // await CalledMethodAsync(millisecondsDelay);
    
                Console.WriteLine("  Returning from calling method.");
            }
    
            static async Task CalledMethodAsync(int millisecondsDelay)
            {
                Console.WriteLine("    Entering called method, starting and awaiting Task.Delay.");
    
                await Task.Delay(millisecondsDelay);
    
                Console.WriteLine("    Task.Delay is finished--returning from called method.");
            }
        }
    
        // Output with Call #1 or Call #2. (Wait for the last line to appear.)
    
        // Entering Main() application entry point.
        //   Entering calling method.
        //     Entering called method, starting and awaiting Task.Delay.
        //   Returning from calling method.
        // Exiting Main() application entry point.
        //     Task.Delay is finished--returning from called method.
    
        // Output with Call #3, which awaits the call to CalledMethodAsync.
    
        // Entering Main() application entry point.
        //   Entering calling method.
        //     Entering called method, starting and awaiting Task.Delay.
        //     Task.Delay is finished--returning from called method.
        //   Returning from calling method.
        // Exiting Main() application entry point.
    }
    
  4. Välj F5-nyckeln för att köra programmet.

Förväntade utdata visas i slutet av koden.

Se även