다음을 통해 공유


한 작업이 완료되면 남은 작업 취소(C# 및 Visual Basic)

사용 하 여는 Task.WhenAny 와 함께 메서드는 CancellationToken, 한 작업이 완료 되 면 나머지 모든 작업을 취소할 수 있습니다.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. 솔루션 탐색기, 바로 가기 메뉴를 엽니다의 CancelAfterOneTask 프로젝트를 하 고 선택 시작 프로젝트로 설정.

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

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

  6. 다른 다운로드를 먼저 완료 확인을 여러 번 실행 하는 프로그램.

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

예제 빌드

이 항목의 예제를 개발 하는 프로젝트 추가 작업 또는 작업 목록 취소(C# 및 Visual Basic) 작업 목록을 취소 합니다.예제 있지만 동일한 UI를 사용 하는 취소 단추를 명시적으로 사용 되지 않습니다.

예제를 빌드하려면 자신 단계를 지시에 따라 "예제 다운로드" 섹션에서 있지만 선택 CancelAListOfTasks시작 프로젝트.변경 내용을이 항목에서 해당 프로젝트에 추가 합니다.

MainWindow.xaml.vb 또는 MainWindow.xaml.cs 파일에는 CancelAListOfTasks 프로젝트에 루프에서 각 웹 사이트에 대 한 처리 단계를 이동 하 여 전환을 시작 AccessTheWebAsync 다음 비동기 메서드.

' ***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
// ***Bundle the processing steps for a website into one async method.
async Task<int> ProcessURLAsync(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;
}

AccessTheWebAsync,이 예제 쿼리를 사용 하는 ToArray<TSource> 메서드 및 WhenAny 배열 작업의 시작 방법.응용 프로그램의 WhenAny 배열에 단일 작업을 갖 경우 반환 배열에 있는 작업의 완료에 도달 하는 첫 번째 작업으로 평가 합니다.

다음과 같이 변경 AccessTheWebAsync.별표는 코드 파일의 변경 내용을 표시합니다.

  1. 주석으로 처리 하거나 루프를 삭제 합니다.

  2. 실행 되 면 쿼리를 만드는 컬렉션을 제네릭 작업 생성 합니다.각 호출에 ProcessURLAsync 반환 된 Task<TResult> 위치 TResult 정수입니다.

    ' ***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)
    
    // ***Create a query that, when executed, returns a collection of tasks.
    IEnumerable<Task<int>> downloadTasksQuery =
        from url in urlList select ProcessURLAsync(url, client, ct);
    
  3. 호출 ToArray 쿼리를 실행 하 고 작업을 시작 합니다.응용 프로그램은 WhenAny 메서드는 다음 단계에서 쿼리를 실행 하 고 사용 하지 않고 작업을 시작 것 ToArray, 하지만 다른 방법이 될 수 있습니다.가장 안전한 방법은 명시적으로 쿼리를 실행 하는 경우

    ' ***Use ToArray to execute the query and start the download tasks. 
    Dim downloadTasks As Task(Of Integer)() = downloadTasksQuery.ToArray()
    
    // ***Use ToArray to execute the query and start the download tasks. 
    Task<int>[] downloadTasks = downloadTasksQuery.ToArray();
    
  4. 호출 WhenAny 작업의 컬렉션입니다.WhenAnyreturns a Task(Of Task(Of Integer)) or Task<Task<int>>.즉, WhenAny 단일 계산 되는 작업을 반환 합니다. Task(Of Integer) 또는 Task<int> 갖 경우.단일 작업 완료 컬렉션에서 첫 번째 작업이입니다.먼저 완료 된 작업에 할당 된 firstFinishedTask.유형을 firstFinishedTask 는 Task<TResult> 위치 TResult 는 반환 형식에는 정수 이므로 ProcessURLAsync.

    ' ***Call WhenAny and then await the result. The task that finishes 
    ' first is assigned to firstFinishedTask.
    Dim firstFinishedTask As Task(Of Integer) = Await Task.WhenAny(downloadTasks)
    
    // ***Call WhenAny and then await the result. The task that finishes 
    // first is assigned to firstFinishedTask.
    Task<int> firstFinishedTask = await Task.WhenAny(downloadTasks);
    
  5. 이 예제에서는 먼저 완료 되는 작업에 관심이.입니다.따라서 사용 CancellationTokenSource.Cancel 작업을 취소 합니다.

    ' ***Cancel the rest of the downloads. You just want the first one.
    cts.Cancel()
    
    // ***Cancel the rest of the downloads. You just want the first one.
    cts.Cancel();
    
  6. 마지막으로 기다립니다 firstFinishedTask 다운로드 된 콘텐츠를 검색할 수 있습니다.

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

다른 다운로드를 먼저 완료 확인을 여러 번 실행 하는 프로그램.

완성된 예제

다음 코드는 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 & "Download complete."

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

        Catch ex As Exception
            resultsTextBox.Text &= vbCrLf & "Download 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()

        '' Comment out or delete the loop.
        ''For Each url In urlList
        ''    ' GetAsync returns a Task(Of HttpResponseMessage). 
        ''    ' Argument ct carries the message if the Cancel button is chosen. 
        ''    ' Note that the Cancel button can cancel all remaining downloads.
        ''    Dim response As HttpResponseMessage = Await client.GetAsync(url, ct)

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

        ''    resultsTextBox.Text &=
        ''        String.Format(vbCrLf & "Length of the downloaded string: {0}." & vbCrLf, urlContents.Length)
        ''Next

        ' ***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 ToArray to execute the query and start the download tasks. 
        Dim downloadTasks As Task(Of Integer)() = downloadTasksQuery.ToArray()

        ' ***Call WhenAny and then await the result. The task that finishes 
        ' first is assigned to firstFinishedTask.
        Dim firstFinishedTask As Task(Of Integer) = Await Task.WhenAny(downloadTasks)

        ' ***Cancel the rest of the downloads. You just want the first one.
        cts.Cancel()

        ' ***Await the first completed task and display the results
        ' Run the program several times to demonstrate that different
        ' websites can finish first.
        Dim length = Await firstFinishedTask
        resultsTextBox.Text &= String.Format(vbCrLf & "Length of the downloaded website:  {0}" & vbCrLf, length)
    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 downloaded website:  158856

' Download 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 CancelAfterOneTask
{
    public partial class MainWindow : Window
    {
        // Declare a System.Threading.CancellationTokenSource.
        CancellationTokenSource cts;

        public MainWindow()
        {
            InitializeComponent();
        }


        private async void startButton_Click(object sender, RoutedEventArgs e)
        {
            // Instantiate the CancellationTokenSource.
            cts = new CancellationTokenSource();

            resultsTextBox.Clear();

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

            // Set the CancellationTokenSource to null when the download is complete.
            cts = null;
        }


        // You can still include a Cancel button if you want to.
        private void cancelButton_Click(object sender, RoutedEventArgs e)
        {
            if (cts != null)
            {
                cts.Cancel();
            }
        }


        // Provide a parameter for the CancellationToken.
        async Task AccessTheWebAsync(CancellationToken ct)
        {
            HttpClient client = new HttpClient();

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

            // ***Comment out or delete the loop.
            //foreach (var url in urlList)
            //{
            //    // GetAsync returns a Task<HttpResponseMessage>. 
            //    // Argument ct carries the message if the Cancel button is chosen. 
            //    // ***Note that the Cancel button can cancel all remaining downloads.
            //    HttpResponseMessage response = await client.GetAsync(url, ct);

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

            //    resultsTextBox.Text +=
            //        String.Format("\r\nLength of the downloaded string: {0}.\r\n", urlContents.Length);
            //}

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

            // ***Use ToArray to execute the query and start the download tasks. 
            Task<int>[] downloadTasks = downloadTasksQuery.ToArray();

            // ***Call WhenAny and then await the result. The task that finishes 
            // first is assigned to firstFinishedTask.
            Task<int> firstFinishedTask = await Task.WhenAny(downloadTasks);

            // ***Cancel the rest of the downloads. You just want the first one.
            cts.Cancel();

            // ***Await the first completed task and display the results. 
            // Run the program several times to demonstrate that different
            // websites can finish first.
            var length = await firstFinishedTask;
            resultsTextBox.Text += String.Format("\r\nLength of the downloaded website:  {0}\r\n", length);
        }


        // ***Bundle the processing steps for a website into one async method.
        async Task<int> ProcessURLAsync(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;
        }


        // Add a method that creates a list of web addresses.
        private List<string> SetUpURLList()
        {
            List<string> urls = new List<string> 
            { 
                "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;
        }
    }
    // Sample output:

    // Length of the downloaded website:  158856

    // Download complete.
}

참고 항목

참조

WhenAny

개념

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

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

기타 리소스

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