Aracılığıyla paylaş


Bir Görev Tamamlandıktan Sonra Kalan Asenkron Görevleri İptal Etme (Visual Basic)

Bir görevi tamamlandığında, Task.WhenAny yöntemini bir CancellationToken ile birlikte kullanarak kalan tüm görevleri iptal edebilirsiniz. WhenAny yöntemi, görevlerden oluşan bir koleksiyonu argüman olarak alır. yöntemi tüm görevleri başlatır ve tek bir görev döndürür. Koleksiyondaki herhangi bir görev tamamlandığında tek görev tamamlanır.

Bu örnek, bir iptal belirtecinin WhenAny ile birlikte nasıl kullanılarak görev koleksiyonundan ilk tamamlanan görevin korunup geri kalan görevlerin iptal edileceğini göstermektedir. Her görev bir web sitesinin içeriğini indirir. Örnek, tamamlanmak üzere ilk indirmenin içeriğinin uzunluğunu görüntüler ve diğer indirmeleri iptal eder.

Uyarı

Örnekleri çalıştırmak için bilgisayarınızda Visual Studio 2012 veya üzeri ve .NET Framework 4.5 veya daha yeni bir sürümü yüklü olmalıdır.

Örneği İndirme

Windows Presentation Foundation (WPF) projesinin tamamını Async Sample: Fine Tuning Your Application adresinden indirebilir ve ardından aşağıdaki adımları izleyebilirsiniz.

  1. İndirdiğiniz dosyayı açarak sıkıştırılmış halini çözün ve ardından Visual Studio'yu başlatın.

  2. Menü çubuğunda Dosya, , Proje/Çözüm'e tıklayın.

  3. Projeyi Aç iletişim kutusunda, sıkıştırmasını kaldırdığınız örnek kodun bulunduğu klasörü açın ve ardından AsyncFineTuningVB için çözüm (.sln) dosyasını açın.

  4. Çözüm Gezgini'ndeCancelAfterOneTask projesinin kısayol menüsünü açın ve ardından Başlangıç Projesi Olarak Ayarla'yı seçin.

  5. Projeyi çalıştırmak için F5 anahtarını seçin.

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

  6. Önce farklı indirmelerin tamamlandığını doğrulamak için programı birkaç kez çalıştırın.

Projeyi indirmek istemiyorsanız, bu konunun sonundaki MainWindow.xaml.vb dosyasını gözden geçirebilirsiniz.

Örneği Oluşturma

Bu konudaki örnek, Zaman Uyumsuz Görev veya Görev Listesini İptal Et başlığında geliştirilen projeye, bir görev listesini iptal etmek amacıyla eklenmiştir. İptal düğmesi açıkça kullanılmasa da örnek aynı kullanıcı arabirimini kullanır.

Örneği kendiniz oluşturmak için, adım adım "Örneği İndirme" bölümündeki yönergeleri izleyin, ancak StartUp Projesi olarak CancelAListOfTasks'i seçin. Bu konudaki değişiklikleri bu projeye ekleyin.

CancelAListOfTasks projesinin MainWindow.xaml.vb dosyasında, her web sitesinin işleme adımlarını döngüden AccessTheWebAsync 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

AccessTheWebAsync bu örnekte, bir sorgu, ToArray yöntemi ve WhenAny yöntemi kullanılarak bir dizi görev oluşturulup başlatılır. WhenAny uygulandığında, görevler dizisindeki tamamlanmaya ulaşan ilk görevi tespit eden ve beklemeye alındığında tek bir görev döndürür.

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

  1. Döngüye açıklama ekleyin veya döngünün silinmesini sağlayın.

  2. Yürütülürken genel görevlerden oluşan bir koleksiyon oluşturan bir sorgu oluşturun. Her ProcessURLAsync çağrısı, Task<TResult> bir tamsayı olduğunda bir TResult döndürü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)
    
  3. Sorguyu yürütmek ve görevleri başlatmak için çağrısı ToArray yapın. Sonraki adımda WhenAny yönteminin uygulanması, sorguyu yürütür ve ToArray kullanmadan görevleri başlatır, ancak diğer yöntemler çalışmayabilir. En güvenli yöntem, sorgunun açıkça yürütülmesini zorlamaktır.

    ' ***Use ToArray to execute the query and start the download tasks.
    Dim downloadTasks As Task(Of Integer)() = downloadTasksQuery.ToArray()
    
  4. Görev koleksiyonunda WhenAny çağrısını yapın. WhenAny, Task(Of Task(Of Integer)) veya Task<Task<int>> döndürür. Başka bir ifadeyle, WhenAny beklenildiğinde, tek bir Task(Of Integer) veya Task<int> döndüren bir görev değerlendirilir. Bu tek görev koleksiyonda bitirecek ilk görevdir. İlk tamamlanan görev finishedTask görevine atanır. finishedTask'nin türü, Task<TResult>'dir çünkü TResult'ün dönüş türü, ProcessURLAsync'nin bir tamsayı olmasını gerektirmektedir.

    ' ***Call WhenAny and then await the result. The task that finishes
    ' first is assigned to finishedTask.
    Dim finishedTask As Task(Of Integer) = Await Task.WhenAny(downloadTasks)
    
  5. Bu örnekte yalnızca ilk olarak biten görevle ilgileniyorsunuz. Bu nedenle, kalan görevleri iptal etmek için kullanın CancellationTokenSource.Cancel .

    ' ***Cancel the rest of the downloads. You just want the first one.
    cts.Cancel()
    
  6. Son olarak, indirilen içeriğin uzunluğunu almayı bekleyin finishedTask .

    Dim length = Await finishedTask
    resultsTextBox.Text &= vbCrLf & $"Length of the downloaded website:  {length}" & vbCrLf
    

Önce farklı indirmelerin tamamlandığını doğrulamak için programı birkaç kez çalıştırın.

Tam Örnek

Aşağıdaki kod, örneğ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.

Dikkat edin, System.Net.Http için bir referans eklemeniz gerekiyor.

Projeyi Asenkron Örnek: Uygulamanıza Hassas Ayar Yapma'dan indirebilirsiniz.

' 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 &=
        ''        vbCrLf & $"Length of the downloaded string: {urlContents.Length}." & vbCrLf
        ''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 finishedTask.
        Dim finishedTask 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 finishedTask
        resultsTextBox.Text &= vbCrLf & $"Length of the downloaded website:  {length}" & vbCrLf
    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/library/hh290138.aspx",
                "https://msdn.microsoft.com/library/hh290140.aspx",
                "https://msdn.microsoft.com/library/dd470362.aspx",
                "https://msdn.microsoft.com/library/aa578028.aspx",
                "https://msdn.microsoft.com/library/ms404677.aspx",
                "https://msdn.microsoft.com/library/ff730837.aspx"
            }
        Return urls
    End Function

End Class

' Sample output:

' Length of the downloaded website:  158856

' Download complete.

Ayrıca bakınız