다음을 통해 공유


작업을 여러 개 시작하고 완료될 때마다 처리(C# 및 Visual Basic)

사용 하 여 Task.WhenAny, 동시에 여러 작업을 시작 하는 완료 것 보다는 시작 하는 순서 대로 처리 하나씩 처리 합니다.

다음 예제에서는 작업의 컬렉션을 만들려면 쿼리를 사용 합니다.각 작업은 지정 된 웹 사이트의 내용을 다운로드합니다.잠시의 각 반복에서 루프 바뀌게 호출 하 여 WhenAny 먼저 다운로드를 완료 하는 작업 컬렉션에는 작업을 반환 합니다.작업 컬렉션에서 제거 되 고 처리 됩니다.컬렉션에 포함 된 작업은 더 이상 때까지 루프를 반복 합니다.

[!참고]

예제를 실행 하려면 Visual Studio 2012 년까지 있어야 익스프레스 Visual Studio 2012 Windows 데스크톱에 대 한, 또는 컴퓨터에 설치 된.NET Framework 4.5.

예제 다운로드

전체 Windows Presentation Foundation (WPF) 프로젝트에서 다운로드할 수 Async 샘플: 미세 튜닝 응용 프로그램 및 다음이 단계를 수행 합니다.

  1. 다운로드 하 고 시작 하는 파일 압축 풀기 Visual Studio 2012.

  2. 메뉴 모음에서 파일, 열기, 프로젝트/솔루션을 선택합니다.

  3. 프로젝트 열기 대화 상자에서 압축 하면, 샘플 코드를 포함 폴더를 연 다음 AsyncFineTuningCS 또는 Asyncfinetuningvb에 대 한 솔루션 (.sln) 파일을 엽니다.

  4. 솔루션 탐색기, 바로 가기 메뉴를 엽니다의 ProcessTasksAsTheyFinish 프로젝트를 하 고 선택 시작 프로젝트로 설정.

  5. 프로젝트를 실행 하려면 F5 키를 선택 합니다.

    디버깅 하지 않고 프로젝트를 실행 하려면 Ctrl + F5 키를 선택 합니다.

  6. 프로젝트를 여러 번 실행 하 여 다운로드 한 길이 항상 동일한 순서로 나타나지 않는 확인 합니다.

프로젝트를 다운로드 하려면이 항목의 끝에 MainWindow.xaml.vb 및 MainWindow.xaml.cs 파일을 검토할 수 있습니다.

예제 빌드

개발 하는 코드를 추가 하는이 예제 한 작업이 완료되면 남은 작업 취소(C# 및 Visual Basic) 와 같은 UI를 사용 합니다.

예제를 빌드하려면 자신 단계를 지시에 따라 "예제 다운로드" 섹션에서 있지만 선택 CancelAfterOneTask시작 프로젝트.변경 내용을이 항목에 추가 된 AccessTheWebAsync 메서드는 프로젝트의.변경 내용은 별표 표시 됩니다.

CancelAfterOneTask 쿼리에 이미 포함 되어 프로젝트는 실행 되 면 작업의 컬렉션을 만듭니다.호출할 때마다 ProcessURLAsync 다음 코드에서 반환 된 Task<TResult> 위치 TResult 정수입니다.

Dim downloadTasksQuery As IEnumerable(Of Task(Of Integer)) =
    From url In urlList Select ProcessURLAsync(url, client, ct)
IEnumerable<Task<int>> downloadTasksQuery =
    from url in urlList select ProcessURL(url, client, ct);

프로젝트의 MainWindow.xaml.vb 또는 MainWindow.xaml.cs 파일에서 다음 변경 하 여 AccessTheWebAsync 메서드.

  • 적용 하 여 쿼리를 실행 합니다. Enumerable.ToList<TSource> 대신 ToArray<TSource>.

    Dim downloadTasks As List(Of Task(Of Integer)) = downloadTasksQuery.ToList()
    
    List<Task<int>> downloadTasks = downloadTasksQuery.ToList();
    
  • 한 동안 추가 컬렉션에 있는 각 작업에 대해 다음 단계를 수행 하는 루프.

    1. 호출을 잠그고 WhenAny 다운로드 완료 컬렉션에서 첫 번째 작업을 식별 합니다.

      Dim firstFinishedTask As Task(Of Integer) = Await Task.WhenAny(downloadTasks)
      
      Task<int> firstFinishedTask = await Task.WhenAny(downloadTasks);
      
    2. 해당 작업을 컬렉션에서 제거합니다.

      downloadTasks.Remove(firstFinishedTask)
      
      downloadTasks.Remove(firstFinishedTask);
      
    3. 잠그고 firstFinishedTask를 호출 하 여 반환 ProcessURLAsync.firstFinishedTask 변수는 Task<TResult> 는 TReturn 정수입니다.작업이 이미 완료 된 있지만 다음 예제와 같이 길이를 다운로드 한 웹 사이트를 검색 하는 작업을 기다립니다.

      Dim length = Await firstFinishedTask
      resultsTextBox.Text &= String.Format(vbCrLf & "Length of the downloaded website:  {0}" & vbCrLf, length)
      
      int length = await firstFinishedTask;
      resultsTextBox.Text += String.Format("\r\nLength of the download:  {0}", length);
      

프로젝트 길이 다운로드 한 순서 대로 항상 나타나지 확인 하려면 여러 번 실행 해야 합니다.

주의 정보주의

사용 하면 WhenAny 루프, 적은 수의 작업 관련 문제를 해결 하는 예제에서 설명한 것 처럼.그러나 다른 방법과 많은 작업을 처리할 수 있는 경우 효율적입니다.자세한 내용 및 예제를 참조 하십시오. 처리 작업으로 완료.

완성된 예제

다음 코드 예제는 MainWindow.xaml.vb 또는 MainWindow.xaml.cs 파일의 전체 텍스트입니다.별표에 대 한이 예제에 추가 된 요소를 표시 합니다.

에 대 한 참조를 추가 해야 System.Net.Http.

프로젝트에서 다운로드할 수 Async 샘플: 미세 튜닝 응용 프로그램.

' Add an Imports directive and a reference for System.Net.Http.
Imports System.Net.Http

' Add the following Imports directive for System.Threading.
Imports System.Threading

Class MainWindow

    ' Declare a System.Threading.CancellationTokenSource.
    Dim cts As CancellationTokenSource


    Private Async Sub startButton_Click(sender As Object, e As RoutedEventArgs)

        ' Instantiate the CancellationTokenSource.
        cts = New CancellationTokenSource()

        resultsTextBox.Clear()

        Try
            Await AccessTheWebAsync(cts.Token)
            resultsTextBox.Text &= vbCrLf & "Downloads complete."

        Catch ex As OperationCanceledException
            resultsTextBox.Text &= vbCrLf & "Downloads canceled." & vbCrLf

        Catch ex As Exception
            resultsTextBox.Text &= vbCrLf & "Downloads failed." & vbCrLf
        End Try

        ' Set the CancellationTokenSource to Nothing when the download is complete.
        cts = Nothing
    End Sub


    ' You can still include a Cancel button if you want to.
    Private Sub cancelButton_Click(sender As Object, e As RoutedEventArgs)

        If cts IsNot Nothing Then
            cts.Cancel()
        End If
    End Sub


    ' Provide a parameter for the CancellationToken.
    ' Change the return type to Task because the method has no return statement.
    Async Function AccessTheWebAsync(ct As CancellationToken) As Task

        Dim client As HttpClient = New HttpClient()

        ' Call SetUpURLList to make a list of web addresses.
        Dim urlList As List(Of String) = SetUpURLList()

        ' ***Create a query that, when executed, returns a collection of tasks.
        Dim downloadTasksQuery As IEnumerable(Of Task(Of Integer)) =
            From url In urlList Select ProcessURLAsync(url, client, ct)

        ' ***Use ToList to execute the query and start the download tasks. 
        Dim downloadTasks As List(Of Task(Of Integer)) = downloadTasksQuery.ToList()

        ' ***Add a loop to process the tasks one at a time until none remain.
        While downloadTasks.Count > 0
            ' ***Identify the first task that completes.
            Dim firstFinishedTask As Task(Of Integer) = Await Task.WhenAny(downloadTasks)

            ' ***Remove the selected task from the list so that you don't
            ' process it more than once.
            downloadTasks.Remove(firstFinishedTask)

            ' ***Await the first completed task and display the results.
            Dim length = Await firstFinishedTask
            resultsTextBox.Text &= String.Format(vbCrLf & "Length of the downloaded website:  {0}" & vbCrLf, length)
        End While

    End Function


    ' Bundle the processing steps for a website into one async method.
    Async Function ProcessURLAsync(url As String, client As HttpClient, ct As CancellationToken) As Task(Of Integer)

        ' GetAsync returns a Task(Of HttpResponseMessage). 
        Dim response As HttpResponseMessage = Await client.GetAsync(url, ct)

        ' Retrieve the website contents from the HttpResponseMessage.
        Dim urlContents As Byte() = Await response.Content.ReadAsByteArrayAsync()

        Return urlContents.Length
    End Function


    ' Add a method that creates a list of web addresses.
    Private Function SetUpURLList() As List(Of String)

        Dim urls = New List(Of String) From
            {
                "https://msdn.microsoft.com",
                "https://msdn.microsoft.com/en-us/library/hh290138.aspx",
                "https://msdn.microsoft.com/en-us/library/hh290140.aspx",
                "https://msdn.microsoft.com/en-us/library/dd470362.aspx",
                "https://msdn.microsoft.com/en-us/library/aa578028.aspx",
                "https://msdn.microsoft.com/en-us/library/ms404677.aspx",
                "https://msdn.microsoft.com/en-us/library/ff730837.aspx"
            }
        Return urls
    End Function

End Class


' Sample output:

' Length of the download:  226093
' Length of the download:  412588
' Length of the download:  175490
' Length of the download:  204890
' Length of the download:  158855
' Length of the download:  145790
' Length of the download:  44908
' Downloads complete.
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 a using directive and a reference for System.Net.Http.
using System.Net.Http;

// Add the following using directive.
using System.Threading;


namespace ProcessTasksAsTheyFinish
{
    public partial class MainWindow : Window
    {
        // Declare a System.Threading.CancellationTokenSource.
        CancellationTokenSource cts;

        public MainWindow()
        {
            InitializeComponent();
        }

        private async void startButton_Click(object sender, RoutedEventArgs e)
        {
            resultsTextBox.Clear();

            // Instantiate the CancellationTokenSource.
            cts = new CancellationTokenSource();

            try
            {
                await AccessTheWebAsync(cts.Token);
                resultsTextBox.Text += "\r\nDownloads complete.";
            }
            catch (OperationCanceledException)
            {
                resultsTextBox.Text += "\r\nDownloads canceled.\r\n";
            }
            catch (Exception)
            {
                resultsTextBox.Text += "\r\nDownloads failed.\r\n";
            }

            cts = null;
        }


        private void cancelButton_Click(object sender, RoutedEventArgs e)
        {
            if (cts != null)
            {
                cts.Cancel();
            }
        }


        async Task AccessTheWebAsync(CancellationToken ct)
        {
            HttpClient client = new HttpClient();

            // Make a list of web addresses.
            List<string> urlList = SetUpURLList();

            // ***Create a query that, when executed, returns a collection of tasks.
            IEnumerable<Task<int>> downloadTasksQuery =
                from url in urlList select ProcessURL(url, client, ct);

            // ***Use ToList to execute the query and start the tasks. 
            List<Task<int>> downloadTasks = downloadTasksQuery.ToList();

            // ***Add a loop to process the tasks one at a time until none remain.
            while (downloadTasks.Count > 0)
            {
                    // Identify the first task that completes.
                    Task<int> firstFinishedTask = await Task.WhenAny(downloadTasks);

                    // ***Remove the selected task from the list so that you don't
                    // process it more than once.
                    downloadTasks.Remove(firstFinishedTask);

                    // Await the completed task.
                    int length = await firstFinishedTask;
                    resultsTextBox.Text += String.Format("\r\nLength of the download:  {0}", length);
            }
        }


        private List<string> SetUpURLList()
        {
            List<string> urls = new List<string> 
            { 
                "https://msdn.microsoft.com",
                "https://msdn.microsoft.com/library/windows/apps/br211380.aspx",
                "https://msdn.microsoft.com/en-us/library/hh290136.aspx",
                "https://msdn.microsoft.com/en-us/library/dd470362.aspx",
                "https://msdn.microsoft.com/en-us/library/aa578028.aspx",
                "https://msdn.microsoft.com/en-us/library/ms404677.aspx",
                "https://msdn.microsoft.com/en-us/library/ff730837.aspx"
            };
            return urls;
        }


        async Task<int> ProcessURL(string url, HttpClient client, CancellationToken ct)
        {
            // GetAsync returns a Task<HttpResponseMessage>. 
            HttpResponseMessage response = await client.GetAsync(url, ct);

            // Retrieve the website contents from the HttpResponseMessage.
            byte[] urlContents = await response.Content.ReadAsByteArrayAsync();

            return urlContents.Length;
        }
    }
}

// Sample Output:

// Length of the download:  226093
// Length of the download:  412588
// Length of the download:  175490
// Length of the download:  204890
// Length of the download:  158855
// Length of the download:  145790
// Length of the download:  44908
// Downloads complete.

참고 항목

참조

WhenAny

개념

Async 응용 프로그램 미세 조정(C# 및 Visual Basic)

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

기타 리소스

Async 샘플: 미세 튜닝 응용 프로그램