コンパイラの警告 (レベル 1) CS4014

この呼び出しは待機されなかったため、現在のメソッドの実行は呼び出しの完了を待たずに続行されます。呼び出しの結果に 'await' 演算子を適用することを検討してください。

現在のメソッドは TaskTask<TResult> を返し、結果に 待機します。 の演算子を追加しない非同期のメソッドを呼び出します。非同期のメソッドの呼び出しが非同期タスクを開始します。ただし、await の演算子が適用されないため、プログラムはタスクが完了するのを待たずに従います。ほとんどの場合、この動作は予期したとおりではありません。通常、のメソッドのそのほかの部分は、呼び出しの結果に依存するまたは呼び出しを含むメソッドから戻る前に、少なくとも、呼び出されたメソッドが完了すると想定されます。

同様に重要な問題は、呼び出された async のメソッド内で発生する例外がどうなっているかです。TaskTask<TResult> を返すメソッド内で発生する例外は、返されたタスクに格納されます。タスクを待たず、例外を明示的にチェックしない場合、例外は失われます。タスクを待機、例外がスローされます。

ベスト プラクティスとして、呼び出しを常に待機する必要があります。

非同期呼び出し完了するのを待機したくない場合、呼び出されたメソッドは例外を発生させないようにする場合にのみ警告を抑制することを検討してください。このケースでは、変数にはタスクの結果を再配置して警告を抑制できます。

次の例では、この警告を抑制する方法を生成する方法と、呼び出しを待機する方法を示します。

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

例では、は #1 を選択するか、または #2 を呼び出して、呼び出し元 (CallingMethodAsync) と呼び出し元の呼び出し元 (startButton_Click両方) の後に unawaited async のメソッド (CalledMethodAsync) の末尾がありません。次の出力の最後の行は、呼び出されたメソッドが完了すると表示されます。エントリに、完全な例に CallingMethodAsync を呼び出すイベント ハンドラーの終了が出力にマークされます。

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.

また、#pragma 警告 (C# リファレンス) ディレクティブを使用してコンパイラの警告を抑制できます。

使用例

Windows Presentation Foundation (WPF) の次のアプリケーションでは、前の例のメソッドが含まれています。次の手順では、アプリケーションが設定されます。

  1. WPF アプリケーションを作成し、AsyncWarningという名前を付けます。

  2. Visual Studio では、エディターを選択します [MainWindow.xaml] のタブを参照してください。

    タブが表示されない場合は、[ソリューション エクスプローラー] で MainWindow.xaml のショートカット メニューを開き、[コードの表示] を選択します。

  3. 次のコードでは、MainWindow.xaml の [XAML] ビューのコードに置き換えます。

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

    ボタンとテキスト ボックスを含む簡単なウィンドウは、MainWindow.xaml の [デザイン] ビューに表示されます。

    XAML デザイナーの詳細については、XAML デザイナーを使用した UI の作成を参照してください。独自の単純な UI を作成する方法の詳細については、"簡単な WPF の MainWindowのデザインする WPF アプリケーションを作成するには" チュートリアル: Async と Await を使用した Web へのアクセス (C# および Visual Basic)のセクションを参照してください。

  4. 次のコードで MainWindow.xaml.cs のコードに置き換えます。

    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. プログラムを実行するには、F5 キーを選択し、を [開始] のボタンをクリックします。

    予想される出力は、コードの最後に表示されます。

参照

関連項目

await (C# リファレンス)

概念

Async および Await を使用した非同期プログラミング (C# および Visual Basic)