Aviso do compilador (nível 1) CS4014

Como esta chamada não é aguardada, a execução do método atual continua antes da conclusão da chamada.Considere aplicar o operador 'await' ao resultado da chamada.

O método atual chama um método de async que retorna Task ou Task e não aplica o operador de aguarde ao resultado. A chamada para o método de async inicia uma tarefa assíncrona. No entanto, como nenhum operador de await é aplicado, o programa continua sem esperar que a tarefa for concluída. Na maioria dos casos, esse comportamento não é o que você espera. Geralmente outros aspectos do método de chamada dependem dos resultados da chamada ou, no mínimo, o método chamado é esperado ser concluída antes que você retorne do método que contém a.

Um problema igualmente importante é o que acontece nas exceções geradas no método chamado de async. Uma exceção gerada em um método que retorna Task ou Task é armazenada em uma tarefa retornado. Se você não espera a tarefa ou explicitamente a verificação para exceções, a exceção será perdida. Se você espera que a tarefa, a exceção é rethrown.

Como prática recomendada, você sempre deve esperar a chamada.

Você deve considerar suprimir o aviso somente se você tiver certeza de que não quiser esperar a chamada assíncrona seja concluída e que o método chamado não gerará nenhuma exceções. Nesse caso, você pode suprimir o aviso ao atribuir o resultado da tarefa de chamada a uma variável.

O exemplo a seguir mostra como gerar um aviso, como suprimi-lo, e como esperar a chamada.

async Task CallingMethodAsync()
{
    resultsTextBox.Text += "\r\n  Entering calling method.";
    // Variable delay is used to slow down the called method so that you can
    // distinguish between awaiting and not awaiting in the program's output.
    // You can adjust the value to produce the output that this topic shows
    // after the code.
    var delay = 5000;

    // 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(delay);

    // 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(delay);

    // 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(delay);

    // If the call to CalledMethodAsync isn't awaited, CallingMethodAsync
    // continues to run and, in this example, finishes its work and returns
    // to its caller.
    resultsTextBox.Text += "\r\n  Returning from calling method.";
}


async Task CalledMethodAsync(int howLong)
{
    resultsTextBox.Text += 
        "\r\n    Entering called method, starting and awaiting Task.Delay.";

    // Slow the process down a little so that you can distinguish between
    // awaiting and not awaiting in the program's output. Adjust the value
    // for howLong if necessary.
    await Task.Delay(howLong);
    resultsTextBox.Text += 
        "\r\n    Task.Delay is finished--returning from called method.";
}

No exemplo, se você escolher a chamada #1 ou chama #2, os termina unawaited do método de asyncCalledMethodAsync() depois do chamadorCallingMethodAsync() e o chamador do chamador (startButton_Click) estão cheios. A última linha na saída a seguir mostra quando o método chamado é concluída. A entrada e a saída do manipulador de eventos que chama CallingMethodAsync no exemplo completo são marcadas na saída.

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.

Você também pode suprimir avisos do compilador usando diretivas de #pragma warning (Referência de C#) .

Exemplo

O seguinte aplicativo do Windows Presentation Foundation (WPF) contém os métodos do exemplo anterior. As etapas a seguir configuram o aplicativo.

  1. Crie um aplicativo de WPF e, nomeie-o AsyncWarning.

  2. No Editor de Códigos do Visual Studio, escolha a guia MainWindow.xaml.

    Se a guia não estiver visível, abra o menu de atalho para MainWindow.xaml em Gerenciador de Soluções, e escolha Exibir Código.

  3. Substitua o código na exibição de XAML de MainWindow.xaml com o código a seguir.

    <Window x:Class="AsyncWarning.MainWindow"
            xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <Button x:Name="startButton" Content="Start" HorizontalAlignment="Left" Margin="214,28,0,0" VerticalAlignment="Top" Width="75" HorizontalContentAlignment="Center" FontWeight="Bold" FontFamily="Aharoni" Click="startButton_Click" />
            <TextBox x:Name="resultsTextBox" Margin="0,80,0,0" TextWrapping="Wrap" FontFamily="Lucida Console"/>
        </Grid>
    </Window>
    

    Uma janela simples que contém um botão e uma caixa de texto aparece na exibição de Design de MainWindow.xaml.

    Para obter mais informações sobre como XAML o Designer, consulte Criando uma interface de usuário usando o Designer XAML. Para obter informações sobre como criar seu próprio interface do usuário simples, consulte “para criar um aplicativo de WPF” e “criar as seções de WPF um MainWindow simples” de Instruções passo a passo: acessando a Web e usando Async e Await (C# e Visual Basic).

  4. Substitua o código em MainWindow.xaml.cs com o código a seguir.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace AsyncWarning
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
    
            private async void startButton_Click(object sender, RoutedEventArgs e)
            {
                resultsTextBox.Text += "\r\nEntering the Click event handler.";
                await CallingMethodAsync();
                resultsTextBox.Text += "\r\nExiting the Click event handler.";
            }
    
    
            async Task CallingMethodAsync()
            {
                resultsTextBox.Text += "\r\n  Entering calling method.";
                // Variable delay is used to slow down the called method so that you can
                // distinguish between awaiting and not awaiting in the program's output.
                // You can adjust the value to produce the output that this topic shows
                // after the code.
                var delay = 5000;
    
                // 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(delay);
    
                // 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(delay);
    
                // 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(delay);
    
                // If the call to CalledMethodAsync isn't awaited, CallingMethodAsync
                // continues to run and, in this example, finishes its work and returns
                // to its caller.
                resultsTextBox.Text += "\r\n  Returning from calling method.";
            }
    
    
            async Task CalledMethodAsync(int howLong)
            {
                resultsTextBox.Text += 
                    "\r\n    Entering called method, starting and awaiting Task.Delay.";
    
                // Slow the process down a little so that you can distinguish between
                // awaiting and not awaiting in the program's output. Adjust the value
                // for howLong if necessary.
                await Task.Delay(howLong);
                resultsTextBox.Text += 
                    "\r\n    Task.Delay is finished--returning from called method.";
            }
        }
    
        // Output with Call #1 or Call #2. (Wait for the last line to appear.)
    
        // 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.
    
    
        // Output with Call #3, which awaits the call to CalledMethodAsync.
    
        // Entering the Click event handler.
        //   Entering calling method.
        //     Entering called method, starting and awaiting Task.Delay.
        //     Task.Delay is finished--returning from called method.
        //   Returning from calling method.
        // Exiting the Click event handler.
    }
    
  5. Escolha a tecla F5 para executar o programa e escolha o botão Iniciar.

    Saídas esperadas aparecem no final do código.

Consulte também

Referência

await (Referência de C#)

Conceitos

Programação assíncrona com Async e Await (C# e Visual Basic)