한 작업이 완료되면 남은 작업 취소(C# 및 Visual Basic)
사용 하 여는 Task.WhenAny 와 함께 메서드는 CancellationToken, 한 작업이 완료 되 면 나머지 모든 작업을 취소할 수 있습니다.WhenAny 메서드는 컬렉션 작업의 인수를 사용 합니다.메서드는 모든 작업을 시작 하 고 단일 작업을 반환 합니다.컬렉션의 모든 작업이 완료 되 면 단일 작업 완료 되었습니다.
취소 토큰을 함께 사용 하는 방법을 보여 주는이 예제 WhenAny 컬렉션에서 작업을 완료 하 고 나머지 작업을 취소 하려면 첫 번째 작업으로 저장할 수 있습니다.각 작업은 웹 사이트의 내용을 다운로드합니다.예제 첫 번째 다운로드가 완료 내용의 길이 표시 하 고 다른 다운로드를 취소 합니다.
[!참고]
예제를 실행 하려면 Visual Studio 2012 년까지 있어야 익스프레스 Visual Studio 2012 Windows 데스크톱에 대 한, 또는 컴퓨터에 설치 된.NET Framework 4.5.
예제 다운로드
전체 Windows Presentation Foundation (WPF) 프로젝트에서 다운로드할 수 Async 샘플: 미세 튜닝 응용 프로그램 및 다음이 단계를 수행 합니다.
다운로드 하 고 시작 하는 파일 압축 풀기 Visual Studio 2012.
메뉴 모음에서 파일, 열기, 프로젝트/솔루션을 선택합니다.
에 프로젝트 열기 대화 상자에서 압축 하면, 샘플 코드를 포함 폴더를 연 다음 AsyncFineTuningCS 또는 Asyncfinetuningvb에 대 한 솔루션 (.sln) 파일을 엽니다.
솔루션 탐색기, 바로 가기 메뉴를 엽니다의 CancelAfterOneTask 프로젝트를 하 고 선택 시작 프로젝트로 설정.
프로젝트를 실행 하려면 F5 키를 선택 합니다.
디버깅 하지 않고 프로젝트를 실행 하려면 Ctrl + F5 키를 선택 합니다.
다른 다운로드를 먼저 완료 확인을 여러 번 실행 하는 프로그램.
프로젝트를 다운로드 하려면이 항목의 끝에 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.별표는 코드 파일의 변경 내용을 표시합니다.
주석으로 처리 하거나 루프를 삭제 합니다.
실행 되 면 쿼리를 만드는 컬렉션을 제네릭 작업 생성 합니다.각 호출에 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);
호출 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();
호출 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);
이 예제에서는 먼저 완료 되는 작업에 관심이.입니다.따라서 사용 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();
마지막으로 기다립니다 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.
}
참고 항목
참조
개념
Async 응용 프로그램 미세 조정(C# 및 Visual Basic)
Async 및 Await를 사용한 비동기 프로그래밍(C# 및 Visual Basic)