Aracılığıyla paylaş


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.

  1. Karşıdan yüklenen ve başlatın dosyasını indirip sıkıştırmasını açın Visual Studio 2012.

  2. Menü çubuğunda, Dosya, , Proje/Çözüm seçeneklerini belirleyin.

  3. İç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.

  4. İçinde Çözüm Gezgini, kısayol menüsünü açmak ProcessTasksAsTheyFinish 'ı seçin ve proje başlangıç projesi olarak ayarla.

  5. 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.

  6. 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.

    1. 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);
      
    2. Bu görev koleksiyonundan kaldırır.

      downloadTasks.Remove(firstFinishedTask)
      
      downloadTasks.Remove(firstFinishedTask);
      
    3. 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ı notuUyarı

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

WhenAny

Kavramlar

Async Uygulamanızda Hassas Ayar Yapma (C# ve Visual Basic)

Zaman uyumsuz zaman uyumsuz programlama ve beklemek (C# ve Visual Basic)

Diğer Kaynaklar

Zaman uyumsuz örnek: İnce uygulamanızı Tuning