Aracılığıyla paylaş


Bir Görev Tamamlandıktan Sonra Geri Kalan Zaman Uyumsuz Görevleri İptal Etme (C# ve Visual Basic)

Task.WhenAny yöntemini bir CancellationToken ile birlikte kullanarak, bir görev tamamlandığında kalan tüm görevleri iptal edebilirsiniz.WhenAny yöntemi, bir görev koleksiyonu olan bir bağımsız değişken alır.Yöntem tüm görevleri başlatır ve tek bir görev döndürür.Koleksiyondaki herhangi bir görev tamamlandığında tek bir görev tamamlanmıştır.

Bu örnek, görevler listesindeki bitirilecek ilk göreve başlamak ve geri kalan görevleri iptal etmek için, WhenAny ile birlikte bir iptal belirtecinin nasıl kullanılacağını gösterir.Her görev, bir web sitesinin içeriklerini karşıdan yükler.Örnek, tamamlanacak ilk yüklemenin içeriğinin uzunluğunu görüntüler ve diğer yüklemeleri iptal eder.

[!NOT]

Örnekleri çalıştırmak için bilgisayarınızda Visual Studio 2012, Visual Studio 2013, Visual Studio Express 2012 for Windows Desktop, Windows için Visual Studio Express 2013 veya .NET Framework 4.5 ya da 4.5.1 yüklü olmalıdır.

Örneği İndirme

Zaman Uyumsuz Örneği: Uygulamanıza İnce Ayar Yapma bölümünden Windows Presentation Foundation (WPF) projesinin tamamını indirebilir ve ardından şu adımları izleyebilirsiniz.

  1. Karşıdan yüklenen sıkıştırılmış dosyayı açın ve daha sonra Visual Studio'yu başlatın.

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

  3. Proje aç iletişim kutusunda, açtığınız örnek kodu barındıran klasörü açın, ardından AsyncFineTuningCS veya AsyncFineTuningVB için çözüm (.sln) dosyasını açın.

  4. Çözüm Gezgini içinde CancelAfterOneTask projesinin kısayol menüsünü açın arından Başlangıç Projesi Olarak Ayarla öğesini seçin.

  5. Projeyi çalıştırmak için F5 tuşuna basın.

    Projeyi hata ayıklama olmadan çalıştırmak için Ctrl + F5 tuşlarını seçin.

  6. Farklı indirmelerin önce bittiğini doğrulamak için programı birkaç kez çalıştırın.

Projeyi indirmek istemiyorsanız, bu konunun sonunda MainWindow.xaml.vb ve MainWindow.xaml.cs dosyalarını gözden geçirebilirsiniz.

Örneği Oluşturma

Bu konudaki örnek, bir görevler listesini iptal etmek için Zaman Uyumsuz bir Görevi veya Görev Listesini İptal Etme (C# ve Visual Basic) konusunda geliştirilen projeye eklemeler yapmaktadır.Örnekte aynı arabirim kullanılmaktadır, ancak İptal düğmesi açıkça kullanılmaz.

Örneği kendiniz oluşturmanız için, "Örneği İndirme" bölümündeki yönergeleri adım adım uygulayın, fakat Başlangıç Projesi olarak CancelAListOfTasks öğesini seçin.Bu konudaki değişiklikleri bu projeye ekleyin.

CancelAListOfTasks projesinin MainWindow.xaml.vb veya MainWindow.xaml.cs dosyasında, her web sitesi için işlenen adımları AccessTheWebAsync konumundaki döngüden aşağıdaki zaman uyumsuz yönteme taşıyarak geçişi başlatın.

' ***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 içinde bir dizi görev oluşturup başlatmak için bu örnekte sorgu, ToArray``1 yöntemi ve WhenAny yöntemi kullanmaktadır. WhenAny öğesinin diziye uygulanması, beklendiğinde görevler listesinde ilk görevin tamamlanmasını değerlendiren tek bir görev döndürür.

AccessTheWebAsync'de aşağıdaki değişiklikleri yapın.Yıldız işaretleri, kod dosyasındaki değişiklikleri işaretler.

  1. Döngüyü açıklama satırı yapın veya silin.

  2. Yürütüldüğünde, bir genel görev koleksiyonu üreten bir sorgu oluşturun.ProcessURLAsync öğesine yapılan her çağrı bir Task getirir; burada TResult bir tamsayıdır.

    ' ***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. Sorguyu yürütmek için ToArray öğesini çağırın ve görevleri başlatın.Sonraki adımda WhenAny yönteminin uygulanması, ToArray kullanmadan sorguyu yürütür ve görevleri başlatır, ancak diğer yöntemler bunu yapmayabilir.En güvenli yöntem sorgu yürütmesini açıkça zorlamaktır.

    ' ***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. Görevler koleksiyonunda WhenAny öğesini çağırın.WhenAny öğesi bir Task(Of Task(Of Integer)) veya Task<Task<int>> döndürür. Yani, WhenAny, beklendiği zaman tek bir Task(Of Integer) veya Task<int> hesaplayan bir görev döndürür.Bu tek görev koleksiyondaki bitirilecek ilk görevdir.Önce tamamlanmış görev firstFinishedTask öğesine atanır.firstFinishedTask türü, Task türüdür; burada TResult bir tamsayıdır çünkü bu ProcessURLAsync dönüş türüdür.

    ' ***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. Bu örnekte, yalnızca ilk biten görevle ilgilendiniz.Bu nedenle, kalan görevleri iptal etmek için CancellationTokenSource.Cancel kullanın.

    ' ***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. Son olarak, karşıdan yüklenen içeriğin uzunluğunu almak için firstFinishedTask öğesini bekleyin.

    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);
    

Farklı indirmelerin önce bittiğini doğrulamak için programı birkaç kez çalıştırın.

Tam Örnek

Aşağıdaki kod, örnek için tam MainWindow.xaml.vb veya MainWindow.xaml.cs dosyasıdır.Yıldız işaretleri, bu örnek için eklenen öğeleri işaretler.

System.Net.Http için bir başvuru eklemeniz gerektiğini unutmayın.

Zaman Uyumsuz Örnek: Uygulamanıza İnce Ayar Yapma içinden projeyi karşıdan yükleyebilirsiniz.

' 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.
}

Ayrıca bkz.

Başvuru

WhenAny

Kavramlar

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

Async ve Await ile Zaman Uyumsuz Programlama (C# ve Visual Basic)

Diğer Kaynaklar

Zaman Uyumsuz Örneği: Uygulamanıza İnce Ayar Yapma