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

この呼び出しは待機されなかったため、現在のメソッドの実行は呼び出しの完了を待たずに続行されます。Because this call is not awaited, execution of the current method continues before the call is completed. 呼び出しの結果に 'await' 演算子を適用することを検討してください。Consider applying the 'await' operator to the result of the call.

現在のメソッドは Task または Task<TResult> を返す非同期メソッドを呼び出し、Await 演算子を結果に適用しません。The current method calls an async method that returns a Task or a Task<TResult> and doesn’t apply the await operator to the result. この非同期メソッドの呼び出しは、非同期タスクを開始します。The call to the async method starts an asynchronous task. ただし、await 演算子が適用されないため、プログラムはタスクの完了を待たずに処理を続行します。However, because no await operator is applied, the program continues without waiting for the task to complete. ほとんどの場合、この動作は想定されるものではありません。In most cases, that behavior isn't what you expect. 通常は、呼び出し元のメソッドの他の側面が呼び出しの結果に依存します。また、最低でも、呼び出しを含むメソッドから制御が返される前に、呼び出されたメソッドが完了することが想定されます。Usually other aspects of the calling method depend on the results of the call or, minimally, the called method is expected to complete before you return from the method that contains the call.

同様に、呼び出された非同期メソッドで発生した例外に対する処理も重要です。An equally important issue is what happens to exceptions that are raised in the called async method. Task または Task<TResult> を返すメソッド内で発生した例外は、返されたタスクに格納されます。An exception that's raised in a method that returns a Task or Task<TResult> is stored in the returned task. このタスクが返されるのを待たない場合や例外を明示的にチェックしない場合、例外は失われます。If you don't await the task or explicitly check for exceptions, the exception is lost. このタスクが返されるのを待機する場合は、例外が再スローされます。If you await the task, its exception is rethrown.

ベスト プラクティスとしては、常に呼び出しを待機する必要があります。As a best practice, you should always await the call.

非同期呼び出しの完了を待つ必要がなく、呼び出されたメソッドで例外が発生しないことが確実である場合に限り、警告を抑制することを検討してください。You should consider suppressing the warning only if you're sure that you don't want to wait for the asynchronous call to complete and that the called method won't raise any exceptions. その場合は、呼び出しのタスクの結果を変数に割り当てることで警告を抑制することができます。In that case, you can suppress the warning by assigning the task result of the call to a variable.

次の例で、警告を発生させる方法、警告を抑制する方法、呼び出しを待機する方法を示します。The following example shows how to cause the warning, how to suppress it, and how to await the call.

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 を選択した場合、完了が待機されない非同期メソッド (CalledMethodAsync) は、呼び出し元 (CallingMethodAsync) と呼び出し元の呼び出し元 (startButton_Click) の両方が完了した後に完了します。In the example, if you choose Call #1 or Call #2, the unawaited async method (CalledMethodAsync) finishes after both its caller (CallingMethodAsync) and the caller's caller (startButton_Click) are complete. 次の出力の最後の行に、呼び出されたメソッドがいつ完了したかが示されています。The last line in the following output shows you when the called method finishes. この出力には、完全な例の CallingMethodAsync を呼び出すイベント ハンドラーへのエントリとその終了が示されています。Entry to and exit from the event handler that calls CallingMethodAsync in the full example are marked in the 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.  

また、#pragma warning ディレクティブを使用してコンパイラの警告を抑制することもできます。You can also suppress compiler warnings by using #pragma warning directives.

Example

次の Windows Presentation Foundation (WPF) アプリケーションには、前の例のメソッドが含まれています。The following Windows Presentation Foundation (WPF) application contains the methods from the previous example. このアプリケーションを設定するには、次の手順を実行します。The following steps set up the application.

  1. WPF アプリケーションを作成し、 AsyncWarningという名前を付けます。Create a WPF application, and name it AsyncWarning.

  2. Visual Studio コード エディターで、 [MainWindow.xaml] タブをクリックします。In the Visual Studio Code Editor, choose the MainWindow.xaml tab.

    タブが表示されない場合は、 ソリューション エクスプローラーで MainWindow.xaml のショートカット メニューを開き、 [コードの表示] を選択します。If the tab isn't visible, open the shortcut menu for MainWindow.xaml in Solution Explorer, and then choose View Code.

  3. MainWindow.xaml の [XAML] ビューで、コードを次のコードに置き換えます。Replace the code in the XAML view of MainWindow.xaml with the following code.

    <Window x:Class="AsyncWarning.MainWindow"  
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
        xmlns:x="http://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 の [デザイン] ビューに表示されます。A simple window that contains a button and a text box appears in the Design view of MainWindow.xaml.

    XAML デザイナーの詳細については、「XAML デザイナーを使用した UI の作成」を参照してください。For more information about the XAML Designer, see Creating a UI by using XAML Designer. 独自の単純な UI を構築する方法については、「チュートリアル: Async と Await を使用した Web へのアクセス」の WPF アプリケーションの作成に関するセクションと単純な WPF MainWindow のデザインに関するセクションを参照してください。Async と Await を使用した Web へのアクセス」をご覧ください。For information about how to build your own simple UI, see the "To create a WPF application" and "To design a simple WPF MainWindow" sections of Walkthrough: Accessing the Web by Using Async and Await.

  4. MainWindow.xaml.cs のコードを次のコードに置き換えます。Replace the code in MainWindow.xaml.cs with the following code.

    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 キーを押してプログラムを実行し、 [Start] を複数回クリックします。Choose the F5 key to run the program, and then choose the Start button.

想定される出力がコードの最後に表示されます。The expected output appears at the end of the code.

関連項目See also