Ostrzeżenie kompilatora (poziom 1) 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.

Bieżąca metoda wywołuje metodę asynchroniową, która zwraca Task obiekt lub i Task<TResult> nie stosuje operatora await do wyniku. Wywołanie metody asynchronicznej rozpoczyna zadanie asynchroniczne. Jednak ze względu na to, że żaden operator nie await jest stosowany, program będzie kontynuowany bez oczekiwania na ukończenie zadania. W większości przypadków takie zachowanie nie jest oczekiwane. Zwykle inne aspekty metody wywołującej zależą od wyników wywołania lub, co najmniej, wywoływana metoda ma zostać ukończona przed zwróceniem z metody zawierającej wywołanie.

Równie ważnym problemem jest to, co dzieje się z wyjątkami zgłoszonymi w wywoływanej metodzie async. Wyjątek zgłoszony w metodzie zwracającej element Task lub Task<TResult> jest przechowywany w zwróconym zadaniu. Jeśli nie oczekujesz na zadanie lub jawnie sprawdź wyjątki, wyjątek zostanie utracony. Jeśli oczekujesz na zadanie, jego wyjątek zostanie ponownie zgłoszony.

Najlepszym rozwiązaniem jest zawsze oczekiwanie na połączenie.

Należy rozważyć pominięcie ostrzeżenia tylko wtedy, gdy na pewno nie chcesz czekać na zakończenie wywołania asynchronicznego i że wywołanie wywoływane przez wywołanie wywołania asynchronicznego nie będzie zgłaszać żadnych wyjątków. W takim przypadku można pominąć ostrzeżenie, przypisując wynik zadania wywołania do zmiennej.

W poniższym przykładzie pokazano, jak spowodować ostrzeżenie, jak go pominąć i jak oczekiwać na wywołanie.

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.");
}

W tym przykładzie, jeśli wybierzesz pozycję Wywołaj #1 lub Wywołaj #2, metoda CalledMethodAsync asynchronizowana zostanie zakończona po CallingMethodAsync zakończeniu zarówno jego wywołującego, jak i wywołującego. Ostatni wiersz w poniższych danych wyjściowych jest wyświetlany po zakończeniu wywoływanej metody. Wpis do i wyjście z programu obsługi zdarzeń, który wywołuje CallingMethodAsync w pełnym przykładzie, są oznaczone w danych wyjściowych.

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.

Można również pominąć ostrzeżenia kompilatora przy użyciu dyrektyw ostrzegawczych #pragma.

Przykład

Poniższa aplikacja konsolowa zawiera metody z poprzedniego przykładu. Poniższe kroki umożliwiają skonfigurowanie aplikacji.

  1. Utwórz aplikację konsolową i nadaj jej AsyncWarningnazwę .

  2. W edytorze programu Visual Studio Code wybierz plik Program.cs .

  3. Zastąp kod w pliku Program.cs następującym kodem.

    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. Wybierz klawisz F5, aby uruchomić program.

Oczekiwane dane wyjściowe są wyświetlane na końcu kodu.

Zobacz też