컴파일러 경고(수준 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. 작업을 기다리는 경우 예외가 다시 throw됩니다.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.";  
}  

이 예제에서는 Call #1 또는 Call #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 디자이너에 대한 자세한 내용은 Visual Studio에서 XAML 디자이너를 사용하여 UI 만들기를 참조하세요.For more information about the XAML Designer, see Creating a UI by using XAML Designer. 간단한 UI를 직접 빌드하는 방법에 대한 자세한 내용은 "WPF 애플리케이션을 만들려면" 섹션과 "간단한 WPF MainWindow를 디자인하려면" 섹션인 연습: Async 및 Await를 사용하여 웹에 액세스를 참조하세요.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 키를 선택하여 프로그램을 실행한 다음 시작 단추를 선택합니다.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