다음을 통해 공유


방법: Async 및 Await를 사용하여 병렬로 여러 웹 요청 만들기(C# 및 Visual Basic)

비동기 메서드의 경우 생성될 때 작업이 시작됩니다. 대기(Visual Basic) 또는 대기(C#) 연산자는 작업이 완료될 때까지 처리가 계속될 수 없는 메서드 지점에서 작업을 적용합니다. 대개는 다음 예제와 같이 작성하는 즉시 작업이 대기됩니다.

Dim result = Await someWebAccessMethodAsync(url)
var result = await someWebAccessMethodAsync(url);

하지만 프로그램이 작업 완료를 의존하지 않는 다른 작업을 수행하는 경우 작업 만들기와 작업 대기를 분리할 수 있습니다.

' The following line creates and starts the task.
Dim myTask = someWebAccessMethodAsync(url)

' While the task is running, you can do other work that does not depend
' on the results of the task.
' . . . . .

' The application of Await suspends the rest of this method until the task is 
' complete.
Dim result = Await myTask
// The following line creates and starts the task.
var myTask = someWebAccessMethodAsync(url);

// While the task is running, you can do other work that doesn't depend
// on the results of the task.
// . . . . .

// The application of await suspends the rest of this method until the task is complete.
var result = await myTask;

작업을 시작하고 기다리는 사이 다른 작업을 시작할 수 있습니다. 추가 작업은 병렬로 암시적으로 실행되지만 추가 스레드는 만들어지지 않습니다.

다음 프로그램은 비동기 웹 다운로드 세 개를 시작한 후 호출된 순서대로 기다립니다. 프로그램을 실행할 때 작업이 항상 만들어지고 대기된 순서대로 완료되는 것은 아닙니다. 작업은 만들면 실행을 시작하고, 메서드가 await 식을 만나기 전에 하나 이상의 작업을 마칠 수 있습니다.

참고

이 프로젝트를 완료하려면 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.WhenAll을 사용하여 비동기 연습 확장(C# 및 Visual Basic)을 참조하십시오.

개발자 코드 샘플에서 이 예제용 코드를 다운로드할 수 있습니다.

프로젝트를 설정하려면

  • WPF 응용 프로그램을 설정하려면 다음 단계를 완료합니다. 이러한 단계에 대한 자세한 지침은 연습: Async 및 Await를 사용하여 웹에 액세스(C# 및 Visual Basic)에 있습니다.

    • 텍스트 상자 및 단추를 포함하는 WPF 응용 프로그램을 만듭니다. startButton 단추를 이름 지정하고 resultsTextBox 입력란을 이름 지정합니다.

    • System.Net.Http에 대해 참조를 추가합니다.

    • MainWindow.xaml.vb 또는 MainWindow.xaml.cs에서 System.Net.Http에 대한 Imports 문 또는 using 지시문을 추가합니다.

코드를 추가하려면

  1. MainWindow.xaml 디자인 창에서 단추를 두 번 클릭하여 MainWindow.xaml.vb 또는 MainWindow.xaml.cs에서 startButton_Click 이벤트 처리기를 만듭니다. 대안으로 단추를 선택하고 속성 창에서 선택한 요소의 이벤트 처리기 아이콘을 선택한 다음 클릭 입력란에 startButton_Click을 입력합니다.

  2. 다음 코드를 복사하고 MainWindow.xaml.vb 또는 MainWindow.xaml.cs에 있는 startButton_Click의 본문에 붙여 넣습니다.

    resultsTextBox.Clear()
    Await CreateMultipleTasksAsync()
    resultsTextBox.Text &= vbCrLf & "Control returned to button1_Click."
    
    resultsTextBox.Clear();
    await CreateMultipleTasksAsync();
    resultsTextBox.Text += "\r\n\r\nControl returned to startButton_Click.\r\n";
    

    이 코드는 응용 프로그램을 관리하는 비동기 메서드 CreateMultipleTasksAsync를 호출합니다.

  3. 다음 지원 메서드를 프로젝트에 추가합니다.

    • ProcessURLAsync는 HttpClient 메서드를 사용하여 바이트 배열로 웹 사이트의 콘텐츠를 다운로드합니다. 그런 다음 지원 메서드 ProcessURLAsync는 배열의 길이를 표시하고 반환합니다.

    • DisplayResults는 각 URL의 바이트 배열의 바이트 수를 표시합니다. 이 표시는 각 작업의 다운로드가 완료되면 나타납니다.

    다음 메서드를 복사하고 MainWindow.xaml.vb 또는 MainWindow.xaml.cs에 있는 startButton_Click 이벤트 처리기 다음에 붙여 넣습니다.

    Private Async Function ProcessURLAsync(url As String, client As HttpClient) As Task(Of Integer)
    
        Dim byteArray = Await client.GetByteArrayAsync(url)
        DisplayResults(url, byteArray)
        Return byteArray.Length
    End Function 
    
    
    Private Sub DisplayResults(url As String, content As Byte())
    
        ' Display the length of each website. The string format  
        ' is designed to be used with a monospaced font, such as 
        ' Lucida Console or Global Monospace. 
        Dim bytes = content.Length
        ' Strip off the "http://". 
        Dim displayURL = url.Replace("http://", "")
        resultsTextBox.Text &= String.Format(vbCrLf & "{0,-58} {1,8}", displayURL, bytes)
    End Sub
    
    async Task<int> ProcessURLAsync(string url, HttpClient client)
    {
        var byteArray = await client.GetByteArrayAsync(url);
        DisplayResults(url, byteArray);
        return byteArray.Length;
    }
    
    
    private void DisplayResults(string url, byte[] content)
    {
        // Display the length of each website. The string format  
        // is designed to be used with a monospaced font, such as 
        // Lucida Console or Global Monospace. 
        var bytes = content.Length;
        // Strip off the "http://".
        var displayURL = url.Replace("http://", "");
        resultsTextBox.Text += string.Format("\n{0,-58} {1,8}", displayURL, bytes);
    }
    
  4. 마지막으로 다음 단계를 수행하는 CreateMultipleTasksAsync 메서드를 정의합니다.

    • 메서드는 GetByteArrayAsync 메서드를 ProcessURLAsync에서 액세스하기 위해 필요한 HttpClient 개체를 선언합니다.

    • 메서드는 TResult가 정수인 Task 형식의 세 가지 작업을 만들고 시작합니다. 각 작업이 완료되면 DisplayResults에 작업의 URL과 다운로드된 콘텐츠의 길이가 표시됩니다. 작업을 비동기적으로 실행하기 때문에 결과가 표시되는 순서는 선언되는 순서와는 다를 수 있습니다.

    • 메서드는 각 작업의 완료를 기다립니다. 각 Await 또는 await 연산자는 대기한 작업이 완료될 때까지 CreateMultipleTasksAsync 실행을 일시 중단합니다. 또한 연산자는 각 완료된 작업의 ProcessURLAsync에 대한 호출에서 반환 값을 검색합니다.

    • 작업이 완료되고 정수 값이 검색되면 메서드는 웹 사이트의 길이를 합산하여 결과를 표시합니다.

    다음 메서드를 복사하여 솔루션에 붙여 넣습니다.

    Private Async Function CreateMultipleTasksAsync() As Task
    
        ' Declare an HttpClient object, and increase the buffer size. The 
        ' default buffer size is 65,536. 
        Dim client As HttpClient =
            New HttpClient() With {.MaxResponseContentBufferSize = 1000000}
    
        ' Create and start the tasks. As each task finishes, DisplayResults  
        ' displays its length. 
        Dim download1 As Task(Of Integer) =
            ProcessURLAsync("https://msdn.microsoft.com", client)
        Dim download2 As Task(Of Integer) =
            ProcessURLAsync("https://msdn.microsoft.com/en-us/library/hh156528(VS.110).aspx", client)
        Dim download3 As Task(Of Integer) =
            ProcessURLAsync("https://msdn.microsoft.com/en-us/library/67w7t67f.aspx", client)
    
        ' Await each task. 
        Dim length1 As Integer = Await download1
        Dim length2 As Integer = Await download2
        Dim length3 As Integer = Await download3
    
        Dim total As Integer = length1 + length2 + length3
    
        ' Display the total count for all of the websites.
        resultsTextBox.Text &= String.Format(vbCrLf & vbCrLf &
                                             "Total bytes returned:  {0}" & vbCrLf, total)
    End Function
    
    private async Task CreateMultipleTasksAsync()
    {
        // Declare an HttpClient object, and increase the buffer size. The 
        // default buffer size is 65,536.
        HttpClient client =
            new HttpClient() { MaxResponseContentBufferSize = 1000000 };
    
        // Create and start the tasks. As each task finishes, DisplayResults  
        // displays its length.
        Task<int> download1 = 
            ProcessURLAsync("https://msdn.microsoft.com", client);
        Task<int> download2 = 
            ProcessURLAsync("https://msdn.microsoft.com/en-us/library/hh156528(VS.110).aspx", client);
        Task<int> download3 = 
            ProcessURLAsync("https://msdn.microsoft.com/en-us/library/67w7t67f.aspx", client);
    
        // Await each task. 
        int length1 = await download1;
        int length2 = await download2;
        int length3 = await download3;
    
        int total = length1 + length2 + length3;
    
        // Display the total count for the downloaded websites.
        resultsTextBox.Text +=
            string.Format("\r\n\r\nTotal bytes returned:  {0}\r\n", total);
    }
    
  5. F5 키를 선택하여 프로그램을 실행한 다음 시작 단추를 선택합니다.

    세 가지 작업이 항상 같은 순서로 완료되지 않거나 그것들이 생성되고 준비된 순서에 따라 반드시 완료될 필요가 있는지를 확인하기 위해서 여러 번 프로그램을 실행합니다.

예제

다음 코드에는 전체 예제가 포함되어 있습니다.

' Add the following Imports statements, and add a reference for System.Net.Http. 
Imports System.Net.Http


Class MainWindow

    Async Sub startButton_Click(sender As Object, e As RoutedEventArgs) Handles startButton.Click
        resultsTextBox.Clear()
        Await CreateMultipleTasksAsync()
        resultsTextBox.Text &= vbCrLf & "Control returned to button1_Click." 
    End Sub 


    Private Async Function CreateMultipleTasksAsync() As Task

        ' Declare an HttpClient object, and increase the buffer size. The 
        ' default buffer size is 65,536. 
        Dim client As HttpClient =
            New HttpClient() With {.MaxResponseContentBufferSize = 1000000}

        ' Create and start the tasks. As each task finishes, DisplayResults  
        ' displays its length. 
        Dim download1 As Task(Of Integer) =
            ProcessURLAsync("https://msdn.microsoft.com", client)
        Dim download2 As Task(Of Integer) =
            ProcessURLAsync("https://msdn.microsoft.com/en-us/library/hh156528(VS.110).aspx", client)
        Dim download3 As Task(Of Integer) =
            ProcessURLAsync("https://msdn.microsoft.com/en-us/library/67w7t67f.aspx", client)

        ' Await each task. 
        Dim length1 As Integer = Await download1
        Dim length2 As Integer = Await download2
        Dim length3 As Integer = Await download3

        Dim total As Integer = length1 + length2 + length3

        ' Display the total count for all of the websites.
        resultsTextBox.Text &= String.Format(vbCrLf & vbCrLf &
                                             "Total bytes returned:  {0}" & vbCrLf, total)
    End Function 


    Private Async Function ProcessURLAsync(url As String, client As HttpClient) As Task(Of Integer)

        Dim byteArray = Await client.GetByteArrayAsync(url)
        DisplayResults(url, byteArray)
        Return byteArray.Length
    End Function 


    Private Sub DisplayResults(url As String, content As Byte())

        ' Display the length of each website. The string format  
        ' is designed to be used with a monospaced font, such as 
        ' Lucida Console or Global Monospace. 
        Dim bytes = content.Length
        ' Strip off the "http://". 
        Dim displayURL = url.Replace("http://", "")
        resultsTextBox.Text &= String.Format(vbCrLf & "{0,-58} {1,8}", displayURL, bytes)
    End Sub 
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;

// Add the following using directive, and add a reference for System.Net.Http. 
using System.Net.Http;


namespace AsyncExample_MultipleTasks
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private async void startButton_Click(object sender, RoutedEventArgs e)
        {
            resultsTextBox.Clear();
            await CreateMultipleTasksAsync();
            resultsTextBox.Text += "\r\n\r\nControl returned to startButton_Click.\r\n";
        }


        private async Task CreateMultipleTasksAsync()
        {
            // Declare an HttpClient object, and increase the buffer size. The 
            // default buffer size is 65,536.
            HttpClient client =
                new HttpClient() { MaxResponseContentBufferSize = 1000000 };

            // Create and start the tasks. As each task finishes, DisplayResults  
            // displays its length.
            Task<int> download1 = 
                ProcessURLAsync("https://msdn.microsoft.com", client);
            Task<int> download2 = 
                ProcessURLAsync("https://msdn.microsoft.com/en-us/library/hh156528(VS.110).aspx", client);
            Task<int> download3 = 
                ProcessURLAsync("https://msdn.microsoft.com/en-us/library/67w7t67f.aspx", client);

            // Await each task. 
            int length1 = await download1;
            int length2 = await download2;
            int length3 = await download3;

            int total = length1 + length2 + length3;

            // Display the total count for the downloaded websites.
            resultsTextBox.Text +=
                string.Format("\r\n\r\nTotal bytes returned:  {0}\r\n", total);
        }


        async Task<int> ProcessURLAsync(string url, HttpClient client)
        {
            var byteArray = await client.GetByteArrayAsync(url);
            DisplayResults(url, byteArray);
            return byteArray.Length;
        }


        private void DisplayResults(string url, byte[] content)
        {
            // Display the length of each website. The string format  
            // is designed to be used with a monospaced font, such as 
            // Lucida Console or Global Monospace. 
            var bytes = content.Length;
            // Strip off the "http://".
            var displayURL = url.Replace("http://", "");
            resultsTextBox.Text += string.Format("\n{0,-58} {1,8}", displayURL, bytes);
        }
    }
}

참고 항목

작업

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

방법: Task.WhenAll을 사용하여 비동기 연습 확장(C# 및 Visual Basic)

개념

Async 및 Await를 사용한 비동기 프로그래밍(C# 및 Visual Basic)