Megosztás a következőn keresztül:


A fennmaradó aszinkron feladatok megszakítása az egyik befejezése után (Visual Basic)

Ha a Task.WhenAny metódust egymással CancellationTokenegyütt használja, az összes fennmaradó tevékenységet megszakíthatja, ha egy tevékenység befejeződött. A WhenAny metódus egy olyan argumentumot használ, amely tevékenységek gyűjteménye. A metódus elindítja az összes tevékenységet, és egyetlen tevékenységet ad vissza. Az egyetlen tevékenység akkor fejeződik be, ha a gyűjtemény bármely tevékenysége befejeződött.

Ez a példa bemutatja, hogyan használhatja a lemondási jogkivonatot WhenAny az első tevékenységhez való ragaszkodáshoz a tevékenységek gyűjteményéből való befejezéshez és a fennmaradó tevékenységek megszakításához. Minden feladat letölti egy webhely tartalmát. A példa az első letöltés tartalmának hosszát jeleníti meg a többi letöltés befejezéséhez és megszakításához.

Feljegyzés

A példák futtatásához telepítve kell lennie a Visual Studio 2012-nek vagy újabbnak, valamint a .NET-keretrendszer 4.5-ös vagy újabb verziójának.

A példa letöltése

Töltse le a teljes Windows megjelenítési alaprendszer (WPF) projektet az Async-mintából: Az alkalmazás finomhangolása, majd kövesse az alábbi lépéseket.

  1. Bontsa ki a letöltött fájlt, majd indítsa el a Visual Studiót.

  2. A menüsávon válassza a Fájl, Megnyitás, Projekt/Megoldás lehetőséget.

  3. A Projekt megnyitása párbeszédpanelen nyissa meg a kibontott mintakódot tartalmazó mappát, majd nyissa meg az AsyncFineTuningVB megoldásfájlját (.sln).

  4. A Megoldáskezelő nyissa meg a CancelAfterOneTask projekt helyi menüjét, majd válassza a Beállítás kezdőprojektként lehetőséget.

  5. A projekt futtatásához válassza az F5 billentyűt.

    A Ctrl+F5 billentyűkombinációval hibakeresés nélkül futtathatja a projektet.

  6. Futtassa többször a programot annak ellenőrzéséhez, hogy a különböző letöltések előbb befejeződnek-e.

Ha nem szeretné letölteni a projektet, a témakör végén áttekintheti a MainWindow.xaml.vb fájlt.

A példa létrehozása

A jelen témakörben szereplő példa hozzáadja a Mégse aszinkron tevékenység vagy a Tevékenységek listájában kifejlesztett projekthez a tevékenységek listájának törléséhez. A példa ugyanazt a felhasználói felületet használja, bár a Mégse gombot nem használja explicit módon.

Ha saját maga szeretné létrehozni a példát, kövesse a "Példa letöltése" szakaszban található utasításokat, de startUp projektként válassza a CancelAListOfTasks lehetőséget. Adja hozzá a jelen témakör módosításait a projekthez.

A CancelAListOfTasks projekt MainWindow.xaml.vb fájljában AccessTheWebAsync kezdje el az áttérést az egyes webhelyek feldolgozási lépéseinek áthelyezésével a hurokból a következő aszinkron metódusba.

' ***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

Ebben a példában AccessTheWebAsyncegy lekérdezést, egy ToArray metódust és egy WhenAny metódust használ egy feladattömb létrehozásához és elindításához. A tömbre való WhenAny alkalmazás egyetlen feladatot ad vissza, amely várakozás esetén kiértékeli az első tevékenységre, hogy befejeződjön a tevékenységtömbben.

Végezze el a következő módosításokat a következőben:AccessTheWebAsync Csillag jelöli a kódfájl módosításait.

  1. Megjegyzést fűzhet a hurokhoz, vagy törölheti azt.

  2. Hozzon létre egy lekérdezést, amely végrehajtásakor általános feladatok gyűjteményét hozza létre. Minden hívás ProcessURLAsync egy Task<TResult> egész TResult számot ad vissza.

    ' ***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. Hívás ToArray a lekérdezés végrehajtására és a feladatok elindítására. A metódus következő lépésben történő WhenAny alkalmazása végrehajtja a lekérdezést, és a feladatokat a használata ToArraynélkül indítja el, más metódusok azonban nem. A legbiztonságosabb eljárás a lekérdezés explicit végrehajtásának kényszerítése.

    ' ***Use ToArray to execute the query and start the download tasks.
    Dim downloadTasks As Task(Of Integer)() = downloadTasksQuery.ToArray()
    
  4. Hívja meg WhenAny a feladatok gyűjteményét. WhenAnya vagy Task<Task<int>>.Task(Of Task(Of Integer)) Vagyis egy olyan feladatot ad vissza, WhenAny amely egyetlen Task(Of Integer)Task<int> vagy a várt állapotban van. Ez az egyetlen tevékenység a gyűjtemény első befejezendő feladata. Az elsőként befejezett tevékenység a következőhöz finishedTaskvan rendelve: . A típus finishedTask az, Task<TResult> ahol TResult egy egész szám van, mert ez a visszatérési ProcessURLAsynctípusa.

    ' ***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. Ebben a példában csak az a tevékenység érdekli, amely először fejeződik be. Ezért használja CancellationTokenSource.Cancel a fennmaradó tevékenységek megszakítására.

    ' ***Cancel the rest of the downloads. You just want the first one.
    cts.Cancel()
    
  6. Végül várja finishedTask meg, hogy lekérje a letöltött tartalom hosszát.

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

Futtassa többször a programot annak ellenőrzéséhez, hogy a különböző letöltések előbb befejeződnek-e.

Példa kitöltése

A következő kód a példa teljes MainWindow.xaml.vb vagy MainWindow.xaml.cs fájlja. Csillag jelöli a példához hozzáadott elemeket.

Figyelje meg, hogy hozzá kell adnia egy hivatkozást a következőhöz System.Net.Http: .

A projektet az Async-mintából töltheti le: Az alkalmazás finomhangolása.

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

Lásd még