Condividi tramite


Avviso del compilatore (livello 1) CS4014

Poiché la chiamata non può essere attesa, l'esecuzione del metodo corrente continua prima del completamento della chiamata.È possibile applicare l'operatore 'await' al risultato della chiamata.

Il metodo correnti chiama un metodo async che restituisce Task o Task e non implementa l'operatore await al risultato. La chiamata al metodo async avvia un'attività asincrona. Tuttavia, poiché alcun operatore await viene applicato, il programma procede senza attendere il completamento dell'attività. Nella maggior parte dei casi, questo comportamento non è quello previsto. In genere altri aspetti di chiamare il metodo dipendono dai risultati della chiamata, o come minimo, il metodo chiamato si prevede termini prima del completamento del metodo che contiene la chiamata.

Un problema ugualmente importante è cosa accade alle eccezioni generate nel metodo async chiamato. Un'eccezione generata in un metodo che restituisce Task o Task viene archiviata nell'attività. Se non si attende l'attività o si controllano in modo esplicito le eccezioni, l'eccezione viene persa. Se si attende l'attività, la relativa eccezione viene generata di nuovo.

Come procedura consigliata, è necessario attendere sempre la chiamata.

Considerare la possibilità di eliminare l'avviso solo se si è certi che non si desidera attendere la chiamata asincrona per completare e che il metodo chiamato non sollevi alcuna eccezione. In tal caso, è possibile eliminare l'avviso assegnando l'attività risultato della chiamata a una variabile.

Nell'esempio seguente viene illustrato come generare l'avviso, come eliminarlo e come attendere la chiamata.

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

Nell'esempio, se si sceglie chiamata #1 o chiamata #2, il metodo async unawaited (CalledMethodAsync) termina dopo che il relativo chiamante (CallingMethodAsync) e il chiamante del chiamante (startButton_Click) sono terminati. L'ultima riga nell'output seguente illustra quando il metodo chiamato completa. L'entrata e l'uscita dal gestore eventi che chiama CallingMethodAsync nell'esempio completo sono contrassegnate nell'output.

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.

È inoltre possibile eliminare gli avvisi del compilatore mediante le direttive #pragma warning (Riferimenti per C#).

Esempio

L'applicazione Windows Presentation Foundation (WPF) seguente contiene metodi dall'esempio precedente. I passaggi seguenti installano l'applicazione.

  1. Creare un'applicazione WPF e denominarla AsyncWarning.

  2. Nell'editor di codice di Visual Studio, scegliere la scheda MainWindow.xaml.

    Se la scheda non è visibile, aprire il menu di scelta rapida per MainWindow.xaml in Esplora soluzioni quindi scegliere Visualizza codice.

  3. Sostituire il codice nella visualizzazione XAML di MainWindow.xaml, con il codice seguente.

    <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 semplice finestra che contiene un pulsante e una casella di testo vengono visualizzati nella visualizzazione Progettazione di MainWindow.xaml.

    Per ulteriori informazioni sulla finestra di progettazione XAML, vedere Creazione di un'interfaccia utente tramite XAML Designer. Per informazioni su come compilare una semplice interfaccia utente, vedere le sezioni "Creare un'applicazione WPF" e "Progettare un semplice MainWindow WPF" di Procedura dettagliata: accesso al Web tramite Async e Await (C# e Visual Basic).

  4. Sostituire il codice in MainWindow.xaml.cs con il codice seguente.

    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. Premere il tasto F5 per eseguire il programma, quindi scegliere il pulsante Avvia.

    L'output previsto viene visualizzato alla fine del codice.

Vedere anche

Riferimenti

await (Riferimenti per C#)

Concetti

Programmazione asincrona con Async e Await (C# e Visual Basic)