Birden Çok Görev Başlatma ve Görevleri Tamamlandıkça İşleme (C# ve Visual Basic)
Kullanarak Task.WhenAny, aynı anda birden çok görevi başlatmak ve bunlar tamamlandı yerine gibi bunlar başladı sırada işlenecekleri tek tek işlem.
Aşağıdaki örnek görevleri bir koleksiyonunu oluşturmak için bir sorgu kullanır.Her görev, belirtilen bir Web sitesinin içeriği karşıdan yükler.Her tekrarında bir while döngüsü, awaited bir çağrı WhenAny görevi, önce kendi yükleme tamamlandıktan topluluğunu Görevler içinde döndürür.Bu görev koleksiyonundan kaldırıldı ve işlenir.Daha fazla görev yok fotoğraflardan kadar döngüyü yineler.
[!NOT]
Örnekleri çalıştırmak için Visual Studio 2012 sahip Visual Studio Express 2012 için Windows Masaüstü, veya bilgisayarınızda yüklü .NET Framework 4.5.
Örnek yükleme
Tam Windows Presentation Foundation (wpf) projeden indirebilirsiniz zaman uyumsuz örnek: ince ayar uygulamanız ve sonra aşağıdaki adımları izleyin.
Karşıdan yüklenen ve başlatın dosyasını indirip sıkıştırmasını açın Visual Studio 2012.
Menü çubuğunda, Dosya, Aç, Proje/Çözüm seçeneklerini belirleyin.
İçinde Açık projeniz iletişim kutusunda, kopyalanırken açılır örnek kodu içeren klasörü açın ve sonra AsyncFineTuningCS veya AsyncFineTuningVB için çözüm (.sln) dosyasını açın.
İçinde Çözüm Gezgini, kısayol menüsünü açmak ProcessTasksAsTheyFinish 'ı seçin ve proje başlangıç projesi olarak ayarla.
F5 tuşuna basarak projeyi çalıştırın seçin.
Projenin hata ayıklama olmadan çalıştırmak için Ctrl + F5 tuşları seçin.
Karşıdan yüklenen uzunlukları aynı sırada her zaman görünmüyor doğrulamak için birkaç kez projeyi çalıştırın.
Proje karşıdan yüklemek istemiyorsanız, bu konunun sonundaki MainWindow.xaml.vb ve MainWindow.xaml.cs dosyalarını gözden geçirebilirsiniz.
Örnek oluşturma
Bu örnek, geliştirilen kod ekler Bir Görev Tamamlandıktan Sonra Geri Kalan Görevleri İptal Etme (C# ve Visual Basic) ve aynı Arabirimi kullanır.
Örnek oluşturmak için kendiniz step by step "Örnek karşıdan yükleme" bölümündeki yönergeleri izleyin, ancak seçim CancelAfterOneTask olarak Başlangıç projesi.Bu başlık altında değişiklikleri eklemek AccessTheWebAsync projedeki yöntemi.Değişiklikler, yıldız işareti ile işaretlenir.
CancelAfterOneTask proje zaten içeren bir sorgu, yürütüldüğünde, görevlerin bir koleksiyon oluşturur.Her çağrı ProcessURLAsync aşağıdaki kodda döndürür bir Task<TResult> burada TResult bir tamsayıdır.
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);
Projenin MainWindow.xaml.vb veya MainWindow.xaml.cs dosyasında aşağıdaki değişiklikleri AccessTheWebAsync yöntem.
Sorguyu yürütmek uygulayarak Enumerable.ToList<TSource> yerine ToArray<TSource>.
Dim downloadTasks As List(Of Task(Of Integer)) = downloadTasksQuery.ToList()
List<Task<int>> downloadTasks = downloadTasksQuery.ToList();
Add while döngüsü koleksiyondaki her görev için aşağıdaki adımları gerçekleştirir.
Bir çağrı bekler WhenAny , yükleme işlemini bitirmek için koleksiyondaki ilk görevi tanımlamak için.
Dim firstFinishedTask As Task(Of Integer) = Await Task.WhenAny(downloadTasks)
Task<int> firstFinishedTask = await Task.WhenAny(downloadTasks);
Bu görev koleksiyonundan kaldırır.
downloadTasks.Remove(firstFinishedTask)
downloadTasks.Remove(firstFinishedTask);
Bekler firstFinishedTask, yapılan bir çağrı tarafından döndürülen ProcessURLAsync.firstFinishedTask Değişken bir Task<TResult> burada TReturn bir tamsayıdır.Görev zaten tamamlandı, ancak aşağıdaki örnekte gösterildiği gibi karşıdan yüklenen Web sitesinin uzunluğu almak için bekler.
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);
Karşıdan yüklenen uzunlukları aynı sırada her zaman görünmüyor doğrulamak için proje birkaç kez çalıştırmalısınız.
Uyarı |
---|
Kullanabileceğiniz WhenAny az sayıda görevleri ilgili sorunları çözmek için örnekte açıklandığı gibi bir döngü içinde.Ancak, diğer yaklaşımları görevleri işlemek için çok sayıda varsa, daha etkili olurlar.Daha fazla bilgi ve örnekler için bkz: İşleme görevleri bunlar tam olarak. |
Tam Örnek
Aşağıdaki kod örneği için MainWindow.xaml.vb veya MainWindow.xaml.cs dosyası tam metindir.Yıldız, bu örnek için eklenmiş öğeleri işaretleyin.
İçin bir başvuru eklemelisiniz dikkat edin System.Net.Http.
Projeden indirebilirsiniz zaman uyumsuz örnek: ince ayar uygulamanız.
' 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.
Ayrıca bkz.
Başvuru
Kavramlar
Async Uygulamanızda Hassas Ayar Yapma (C# ve Visual Basic)
Zaman uyumsuz zaman uyumsuz programlama ve beklemek (C# ve Visual Basic)