Advertencia del compilador (nivel 1) CS4014

Como esta llamada no es 'awaited', la ejecución del método actual continuará antes de que se complete la llamada.Considere la posibilidad de aplicar el operador 'await' al resultado de la llamada.

Las llamadas al método actuales un método async que devuelve Task o Task y no aplica el operador de espera al resultado. La llamada al método async inicia una tarea asincrónica. Sin embargo, porque no se aplica ningún operador de await , el programa continúa sin esperar a que la tarea se complete. En la mayoría de los casos, ese comportamiento no es lo que esperaba. Otros aspectos del método de llamada dependen normalmente de los resultados de la llamada o, como mínimo, se espera que el método denominado se completa antes de volver del método que contiene la llamada.

Un problema igualmente importante sucede a las excepciones que se producen en el método denominado async. Una excepción que se produce en un método que devuelve Task o Task se almacena en la tarea devuelta. Si no espera la tarea o explícitamente la comprobación de excepciones, se pierde la excepción. Si se espera la tarea, la excepción se reinician.

Como procedimiento recomendado, debería aguardar siempre la llamada.

Debería considerar suprimir la advertencia sólo si está seguro de que no desea esperar la llamada asincrónica finalice y que el método denominado no producirá ninguna excepción. En ese caso, puede suprimir la advertencia asignando el resultado de la tarea de la llamada a una variable.

El ejemplo siguiente se muestra cómo provocar la advertencia, cómo suprimirla, y cómo aguardar llamada.

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

En el ejemplo, si elige la llamada n.º o llama #2, finaliza el método unawaited async (CalledMethodAsync) finaliza después del llamador (CallingMethodAsync) y el llamador del llamador (startButton_Click). La última línea en el resultado siguiente muestra cuando el método denominado finaliza. Marca la entrada a y la salida del controlador de eventos que llama a CallingMethodAsync en el ejemplo completo en el resultado.

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.

También puede suprimir las advertencias del compilador mediante las directivas de #pragma warning (Referencia de C#) .

Ejemplo

La siguiente aplicación de (WPF) de Windows Presentation Foundation contiene los métodos del ejemplo anterior. Los pasos siguientes configurar la aplicación.

  1. Cree una aplicación WPF, y denomínela AsyncWarning.

  2. En el Editor de código de Visual Studio, elija la pestaña MainWindow.xaml.

    Si la ficha no está visible, abra el menú contextual para MainWindow.xaml en Explorador de solucionesy, a continuación Ver código.

  3. Reemplace el código en la vista de XAML de MainWindow.xaml con el código siguiente.

    <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>
    

    Una ventana simple que contiene un botón y un cuadro de texto aparece en la vista de Diseñar MainWindow.xaml.

    Para obtener más información sobre el XAML Designer, vea Tutorial: Crear una UI usando el Diseñador XAML. Para obtener información sobre cómo compilar dispone de interfaz de usuario sencilla, vea “para crear una aplicación WPF” y “para diseñar las secciones de WPF un MainWindow simple” de Walkthrough: Acceso a web usando Async y Await (C# y Visual Basic).

  4. Reemplace el código en MainWindow.xaml.cs con el código siguiente.

    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. Elija la tecla F5 para ejecutar el programa y, a continuación, el botón Iniciar.

    La salida esperada aparece al final del código.

Vea también

Referencia

await (Referencia de C#)

Conceptos

Programación asincrónica con Async y Await (C# y Visual Basic)