다음을 통해 공유


비동기 반환 형식(C# 및 Visual Basic)

Async 메서드에는 세 가지 반환 유형, 즉, Task, Task 및 void가 있습니다. Visual Basic에서 void 반환 형식이 Sub 절차로 기록됩니다. 비동기 메서드에 대한 자세한 내용은 Async 및 Await를 사용한 비동기 프로그래밍(C# 및 Visual Basic)을 참조하십시오.

다음 단원 중 하나에서 각 반환 형식을 검사하고 항목 끝에서 모든 세 가지 형식을 사용하는 완벽한 샘플을 찾을 수 있습니다.

참고

예제를 실행하려면 Visual Studio 2012, Visual Studio 2013, Visual Studio Express 2012 for Windows Desktop, Visual Studio Express 2013 for Windows 또는 .NET Framework 4.5이나 4.5.1이 컴퓨터에 설치되어 있어야 합니다.

이 항목에는 다음 단원이 포함되어 있습니다.

  • Task(T) 반환 형식
  • 작업 반환 형식
  • void 반환 형식
  • 완성된 예제
  • 관련 항목

Task(T) 반환 형식

Task 반환 형식은 피연산자가 형식 TResult인 Return(Visual Basic) 또는 return(C#) 문을 포함하는 비동기 메서드에 사용됩니다.

다음 예제에서 TaskOfT_MethodAsync 비동기 메서드에는 정수를 반환하는 return 문이 포함됩니다. 따라서 메서드 선언은 Visual Basic의 경우 Task(Of Integer)와 C#의 경우 Task<int>의 반환 형식을 지정해야 합니다.

' TASK(OF T) EXAMPLE
Async Function TaskOfT_MethodAsync() As Task(Of Integer)

    ' The body of an async method is expected to contain an awaited  
    ' asynchronous call. 
    ' Task.FromResult is a placeholder for actual work that returns a string. 
    Dim today As String = Await Task.FromResult(Of String)(DateTime.Now.DayOfWeek.ToString())

    ' The method then can process the result in some way. 
    Dim leisureHours As Integer 
    If today.First() = "S" Then
        leisureHours = 16
    Else
        leisureHours = 5
    End If 

    ' Because the return statement specifies an operand of type Integer, the  
    ' method must have a return type of Task(Of Integer).  
    Return leisureHours
End Function
// TASK<T> EXAMPLE
async Task<int> TaskOfT_MethodAsync()
{
    // The body of the method is expected to contain an awaited asynchronous 
    // call. 
    // Task.FromResult is a placeholder for actual work that returns a string. 
    var today = await Task.FromResult<string>(DateTime.Now.DayOfWeek.ToString());

    // The method then can process the result in some way. 
    int leisureHours;
    if (today.First() == 'S')
        leisureHours = 16;
    else
        leisureHours = 5;

    // Because the return statement specifies an operand of type int, the 
    // method must have a return type of Task<int>. 
    return leisureHours;
}

TaskOfT_MethodAsync가 await 식 내에서 호출되면 await 식은 TaskOfT_MethodAsync에서 반환된 작업에 저장된 정수 값(leisureHours의 값)을 검색합니다. await 식에 대한 자세한 내용은 Await 연산자(Visual Basic) 또는 await(C# 참조)을 참조하십시오.

다음 코드는 TaskOfT_MethodAsync 메서드를 호출하고 기다립니다. 결과는 result1 변수에 할당됩니다.

' Call and await the Task(Of T)-returning async method in the same statement. 
Dim result1 As Integer = Await TaskOfT_MethodAsync()
// Call and await the Task<T>-returning async method in the same statement. 
int result1 = await TaskOfT_MethodAsync();

다음 코드와 같이 Await 또는 await의 응용 프로그램에서 TaskOfT_MethodAsync에 대한 호출을 구분하여 과정을 더 잘 이해할 수 있습니다. 즉시 대기하지 않는 TaskOfT_MethodAsync 메서드 호출은 메서드 선언에서 예상할 수 있는 Task(Of Integer) 또는 Task<int>를 반환합니다. 작업은 예제의 integerTask 변수에 할당됩니다. integerTask는 Task이므로 TResult 형식의 Result 속성이 포함됩니다. 이 경우 TResult는 정수 형식을 나타냅니다. Await 또는 await가 integerTask에 적용되면 await 식은 integerTask의 Result 속성의 내용으로 확인됩니다. 값이 result2 변수에 할당됩니다.

경고

Result 속성은 차단 속성입니다.해당 작업을 완료하기 전에 액세스하는 경우 현재 활성 상태인 스레드는 작업이 완료되고 해당 값을 사용할 때까지 차단됩니다.대부분의 경우 속성에 직접 액세스하지 않고 Await 또는 await을 사용하여 값에 액세스해야 합니다.

' Call and await in separate statements. 
Dim integerTask As Task(Of Integer) = TaskOfT_MethodAsync()

' You can do other work that does not rely on resultTask before awaiting.
textBox1.Text &= String.Format("Application can continue working while the Task(Of T) runs. . . . " & vbCrLf)

Dim result2 As Integer = Await integerTask
// Call and await in separate statements.
Task<int> integerTask = TaskOfT_MethodAsync();

// You can do other work that does not rely on integerTask before awaiting.
textBox1.Text += String.Format("Application can continue working while the Task<T> runs. . . . \r\n");

int result2 = await integerTask;

다음 코드의 표시 문은 result1 변수의 값, result2 변수 및 Result이 같다는 것을 확인합니다. Result 속성은 속성을 차단하고 해당 작업이 준비되기 전에 액세스할 수 없습니다.

' Display the values of the result1 variable, the result2 variable, and 
' the resultTask.Result property.
textBox1.Text &= String.Format(vbCrLf & "Value of result1 variable:   {0}" & vbCrLf, result1)
textBox1.Text &= String.Format("Value of result2 variable:   {0}" & vbCrLf, result2)
textBox1.Text &= String.Format("Value of resultTask.Result:  {0}" & vbCrLf, integerTask.Result)
// Display the values of the result1 variable, the result2 variable, and 
// the integerTask.Result property.
textBox1.Text += String.Format("\r\nValue of result1 variable:   {0}\r\n", result1);
textBox1.Text += String.Format("Value of result2 variable:   {0}\r\n", result2);
textBox1.Text += String.Format("Value of integerTask.Result: {0}\r\n", integerTask.Result);

작업 반환 형식

return 문을 포함하지 않는 또는 피연산자를 반환하지 않는 return 문이 포함된 비동기 메서드는 일반적으로Task의 반환 형식을 가집니다. 이러한 메서드는 동기적으로 실행하도록 작성된 경우 보이드를 반환한 메서드(Visual Basic의 하위 절차)입니다. 비동기 메서드의 Task 반환 형식을 사용하는 경우 호출 메서드는 await 연산자를 사용하여 호출된 비동기 메서드가 완료될 때까지 호출자의 완료를 일시 중지시킵니다.

다음 예제에서 비동기 메서드 Task_MethodAsync에는 return 문이 포함되지 않습니다. 따라서 사용자가 메서드에 대한 Task의 반환 형식을 지정하면 Task_MethodAsync를 기다릴 수 있습니다. Task 형식의 정의에는 반환 값을 저장할 Result 속성이 포함되어 있지 않습니다.

' TASK EXAMPLE
Async Function Task_MethodAsync() As Task

    ' The body of an async method is expected to contain an awaited  
    ' asynchronous call. 
    ' Task.Delay is a placeholder for actual work.
    Await Task.Delay(2000)
    textBox1.Text &= String.Format(vbCrLf & "Sorry for the delay. . . ." & vbCrLf)

    ' This method has no return statement, so its return type is Task.  
End Function
// TASK EXAMPLE
async Task Task_MethodAsync()
{
    // The body of an async method is expected to contain an awaited  
    // asynchronous call. 
    // Task.Delay is a placeholder for actual work.
    await Task.Delay(2000);
    // Task.Delay delays the following line by two seconds.
    textBox1.Text += String.Format("\r\nSorry for the delay. . . .\r\n");

    // This method has no return statement, so its return type is Task.  
}

Task_MethodAsync는 동기화된 Sub 또는 보이드 반환 메서드와 비슷한 대기 식 대신 대기 문을 사용함으로써 호출하고 대기합니다. 이 경우 await 연산자를 적용해도 값이 생성되지 않습니다.

다음 코드는 Task_MethodAsync 메서드를 호출하고 기다립니다.

' Call and await the Task-returning async method in the same statement.
Await Task_MethodAsync()
// Call and await the Task-returning async method in the same statement.
await Task_MethodAsync();

이전 Task 예제와 마찬가지로 다음 코드가 보여주듯이 Task_MethodAsync에 대한 호출을 await 연산자에서 분리할 수 있습니다. 하지만 Task에는 Result 속성이 없으며 대기 연산자가 Task에 적용되는 경우 어떠한 값도 산출하지 않습니다.

다음 코드는 Task_MethodAsync이 반환하는 작업을 대기하는 것과 Task_MethodAsync 호출을 구분합니다.

' Call and await in separate statements. 
Dim simpleTask As Task = Task_MethodAsync()

' You can do other work that does not rely on simpleTask before awaiting.
textBox1.Text &= String.Format(vbCrLf & "Application can continue working while the Task runs. . . ." & vbCrLf)

Await simpleTask
// Call and await in separate statements.
Task simpleTask = Task_MethodAsync();

// You can do other work that does not rely on simpleTask before awaiting.
textBox1.Text += String.Format("\r\nApplication can continue working while the Task runs. . . .\r\n");

await simpleTask;

void 반환 형식

void 반환 형식(Visual Basic의 경우 Sub 프로시저)은 주로 void 반환 형식이 필요한 이벤트 처리기에서 사용합니다. void 반환은 void를 반환하는 메서드 또는 "실행 후 제거"로 분류될 수 있는 활동을 수행하는 메서드를 재정의하는 데 사용할 수 있습니다 그러나 void 반환 비동기 메서드는 대기할 수 없으므로 가능하면 Task를 반환해야 합니다. 이런 메서드의 호출자는 호출된 비동기 메서드가 완료되기를 기다리지 않고 계속하여 완료할 수 있어야 하며 호출자는 비동기 메서드가 생성되는 값 또는 예외에 대해 독립적이어야 합니다.

Void 반환 비동기 메서드 호출자는 메서드에서 throw된 예외를 캐치할 수 없습니다. 이러한 처리되지 않은 예외들은 응용 프로그램 실패를 발생할 수 있습니다. 예외가 Task 또는 Task를 반환하는 비동기 메서드에서 발생하는 경우 해당 예외를 반환된 작업에 저장하고 작업 대기 중에 다시 throw합니다. 따라서 예외를 생성할 수 있는 모든 비동기 메서드에 Task 또는 Task의 반환 형식이 있는지와 메서드에 대한 해당 호출을 대기 중인지 확인합니다.

비동기 메서드에서 예외를 catch하는 방법에 대한 자세한 내용은 try-catch(C# 참조) 또는 Try...Catch...Finally 문(Visual Basic)를 참조하십시오.

다음 코드는 비동기 이벤트 처리기를 정의합니다.

' SUB EXAMPLE
Async Sub button1_Click(sender As Object, e As RoutedEventArgs) Handles button1.Click

    textBox1.Clear()

    ' Start the process and await its completion. DriverAsync is a  
    ' Task-returning async method.
    Await DriverAsync()

    ' Say goodbye.
    textBox1.Text &= vbCrLf & "All done, exiting button-click event handler." 
End Sub
// VOID EXAMPLE 
private async void button1_Click(object sender, RoutedEventArgs e)
{
    textBox1.Clear();

    // Start the process and await its completion. DriverAsync is a  
    // Task-returning async method.
    await DriverAsync();

    // Say goodbye.
    textBox1.Text += "\r\nAll done, exiting button-click event handler.";
}

완성된 예제

다음 WPF(Windows Presentation Foundation) 프로젝트는 이 항목의 코드 예제를 포함합니다.

프로젝트를 실행하려면 다음 단계를 수행합니다.

  1. Visual Studio를 시작합니다.

  2. 메뉴 모음에서 파일, 새로 만들기, 프로젝트를 선택합니다.

    새 프로젝트 대화 상자가 열립니다.

  3. 설치됨템플릿 범주에서 Visual Basic 또는 **Visual C#**을 선택한 다음 Windows를 선택합니다. 프로젝트 형식 목록에서 WPF 응용 프로그램을 선택합니다.

  4. 프로젝트 이름으로 AsyncReturnTypes를 입력한 다음 확인 단추를 선택합니다.

    솔루션 탐색기에 새 프로젝트가 나타납니다.

  5. Visual Studio 코드 편집기에서 MainWindow.xaml 탭을 선택합니다.

    탭이 표시되지 않는 경우 솔루션 검색기에서 MainPage.xaml의 바로 가기 메뉴를 연 다음 열기를 선택합니다.

  6. MainWindow.xaml의 XAML 창에서 코드를 다음 코드로 바꿉니다.

    <Window x:Class="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="button1" Content="Start" HorizontalAlignment="Left" Margin="214,28,0,0" VerticalAlignment="Top" Width="75" HorizontalContentAlignment="Center" FontWeight="Bold" FontFamily="Aharoni" Click="button1_Click"/>
            <TextBox x:Name="textBox1" Margin="0,80,0,0" TextWrapping="Wrap" FontFamily="Lucida Console"/>
    
        </Grid>
    </Window>
    
    <Window x:Class="AsyncReturnTypes.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="button1" Content="Start" HorizontalAlignment="Left" Margin="214,28,0,0" VerticalAlignment="Top" Width="75" HorizontalContentAlignment="Center" FontWeight="Bold" FontFamily="Aharoni" Click="button1_Click"/>
            <TextBox x:Name="textBox1" Margin="0,80,0,0" TextWrapping="Wrap" FontFamily="Lucida Console"/>
    
        </Grid>
    </Window>
    

    텍스트 상자 및 단추가 포함된 간단한 창이 MainWindow.xaml의 디자인 창에 나타납니다.

  7. 솔루션 탐색기에서 MainWindow.xaml.vb 또는 MainWindow.xaml.cs의 바로 가기 메뉴를 열고 코드 보기를 선택합니다.

  8. MainWindow.xaml.vb 또는 MainWindow.xaml.cs에서 코드를 다음 코드로 바꿉니다.

    Class MainWindow
    
        ' SUB EXAMPLE
        Async Sub button1_Click(sender As Object, e As RoutedEventArgs) Handles button1.Click
    
            textBox1.Clear()
    
            ' Start the process and await its completion. DriverAsync is a  
            ' Task-returning async method.
            Await DriverAsync()
    
            ' Say goodbye.
            textBox1.Text &= vbCrLf & "All done, exiting button-click event handler." 
        End Sub
    
    
        Async Function DriverAsync() As Task
    
            ' Task(Of T)  
            ' Call and await the Task(Of T)-returning async method in the same statement. 
            Dim result1 As Integer = Await TaskOfT_MethodAsync()
    
            ' Call and await in separate statements. 
            Dim integerTask As Task(Of Integer) = TaskOfT_MethodAsync()
    
            ' You can do other work that does not rely on resultTask before awaiting.
            textBox1.Text &= String.Format("Application can continue working while the Task(Of T) runs. . . . " & vbCrLf)
    
            Dim result2 As Integer = Await integerTask
    
            ' Display the values of the result1 variable, the result2 variable, and 
            ' the resultTask.Result property.
            textBox1.Text &= String.Format(vbCrLf & "Value of result1 variable:   {0}" & vbCrLf, result1)
            textBox1.Text &= String.Format("Value of result2 variable:   {0}" & vbCrLf, result2)
            textBox1.Text &= String.Format("Value of resultTask.Result:  {0}" & vbCrLf, integerTask.Result)
    
            ' Task  
            ' Call and await the Task-returning async method in the same statement.
            Await Task_MethodAsync()
    
            ' Call and await in separate statements. 
            Dim simpleTask As Task = Task_MethodAsync()
    
            ' You can do other work that does not rely on simpleTask before awaiting.
            textBox1.Text &= String.Format(vbCrLf & "Application can continue working while the Task runs. . . ." & vbCrLf)
    
            Await simpleTask
        End Function 
    
    
        ' TASK(OF T) EXAMPLE
        Async Function TaskOfT_MethodAsync() As Task(Of Integer)
    
            ' The body of an async method is expected to contain an awaited  
            ' asynchronous call. 
            ' Task.FromResult is a placeholder for actual work that returns a string. 
            Dim today As String = Await Task.FromResult(Of String)(DateTime.Now.DayOfWeek.ToString())
    
            ' The method then can process the result in some way. 
            Dim leisureHours As Integer 
            If today.First() = "S" Then
                leisureHours = 16
            Else
                leisureHours = 5
            End If 
    
            ' Because the return statement specifies an operand of type Integer, the  
            ' method must have a return type of Task(Of Integer).  
            Return leisureHours
        End Function 
    
    
        ' TASK EXAMPLE
        Async Function Task_MethodAsync() As Task
    
            ' The body of an async method is expected to contain an awaited  
            ' asynchronous call. 
            ' Task.Delay is a placeholder for actual work.
            Await Task.Delay(2000)
            textBox1.Text &= String.Format(vbCrLf & "Sorry for the delay. . . ." & vbCrLf)
    
            ' This method has no return statement, so its return type is Task.  
        End Function 
    
    End Class
    
    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 AsyncReturnTypes
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
    
            // VOID EXAMPLE 
            private async void button1_Click(object sender, RoutedEventArgs e)
            {
                textBox1.Clear();
    
                // Start the process and await its completion. DriverAsync is a  
                // Task-returning async method.
                await DriverAsync();
    
                // Say goodbye.
                textBox1.Text += "\r\nAll done, exiting button-click event handler.";
            }
    
            async Task DriverAsync()
            {
                // Task<T>  
                // Call and await the Task<T>-returning async method in the same statement. 
                int result1 = await TaskOfT_MethodAsync();
    
                // Call and await in separate statements.
                Task<int> integerTask = TaskOfT_MethodAsync();
    
                // You can do other work that does not rely on integerTask before awaiting.
                textBox1.Text += String.Format("Application can continue working while the Task<T> runs. . . . \r\n");
    
                int result2 = await integerTask;
    
                // Display the values of the result1 variable, the result2 variable, and 
                // the integerTask.Result property.
                textBox1.Text += String.Format("\r\nValue of result1 variable:   {0}\r\n", result1);
                textBox1.Text += String.Format("Value of result2 variable:   {0}\r\n", result2);
                textBox1.Text += String.Format("Value of integerTask.Result: {0}\r\n", integerTask.Result);
    
                // Task 
                // Call and await the Task-returning async method in the same statement.
                await Task_MethodAsync();
    
                // Call and await in separate statements.
                Task simpleTask = Task_MethodAsync();
    
                // You can do other work that does not rely on simpleTask before awaiting.
                textBox1.Text += String.Format("\r\nApplication can continue working while the Task runs. . . .\r\n");
    
                await simpleTask;
            }
    
            // TASK<T> EXAMPLE
            async Task<int> TaskOfT_MethodAsync()
            {
                // The body of the method is expected to contain an awaited asynchronous 
                // call. 
                // Task.FromResult is a placeholder for actual work that returns a string. 
                var today = await Task.FromResult<string>(DateTime.Now.DayOfWeek.ToString());
    
                // The method then can process the result in some way. 
                int leisureHours;
                if (today.First() == 'S')
                    leisureHours = 16;
                else
                    leisureHours = 5;
    
                // Because the return statement specifies an operand of type int, the 
                // method must have a return type of Task<int>. 
                return leisureHours;
            }
    
    
            // TASK EXAMPLE
            async Task Task_MethodAsync()
            {
                // The body of an async method is expected to contain an awaited  
                // asynchronous call. 
                // Task.Delay is a placeholder for actual work.
                await Task.Delay(2000);
                // Task.Delay delays the following line by two seconds.
                textBox1.Text += String.Format("\r\nSorry for the delay. . . .\r\n");
    
                // This method has no return statement, so its return type is Task.  
            }
        }
    }
    
  9. F5 키를 선택하여 프로그램을 실행한 다음 시작 단추를 선택합니다.

    다음과 같은 출력이 나타나야 합니다.

    Application can continue working while the Task<T> runs. . . . 
    
    Value of result1 variable:   5
    Value of result2 variable:   5
    Value of integerTask.Result: 5
    
    Sorry for the delay. . . .
    
    Application can continue working while the Task runs. . . .
    
    Sorry for the delay. . . .
    
    All done, exiting button-click event handler.
    

참고 항목

작업

연습: Async 및 Await를 사용하여 웹에 액세스(C# 및 Visual Basic)

연습: Async 메서드에 디버거 사용

참조

async(C# 참조)

Async(Visual Basic)

Await 연산자(Visual Basic)

await(C# 참조)

FromResult``1

개념

비동기 프로그램의 제어 흐름(C# 및 Visual Basic)