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.
Bontsa ki a letöltött fájlt, majd indítsa el a Visual Studiót.
A menüsávon válassza a Fájl, Megnyitás, Projekt/Megoldás lehetőséget.
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).
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.
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.
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 AccessTheWebAsync
egy 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.
Megjegyzést fűzhet a hurokhoz, vagy törölheti azt.
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észTResult
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)
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álataToArray
né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()
Hívja meg
WhenAny
a feladatok gyűjteményét.WhenAny
a vagyTask<Task<int>>
.Task(Of Task(Of Integer))
Vagyis egy olyan feladatot ad vissza,WhenAny
amely egyetlenTask(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özfinishedTask
van rendelve: . A típusfinishedTask
az, Task<TResult> aholTResult
egy egész szám van, mert ez a visszatérésiProcessURLAsync
tí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)
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()
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
Visszajelzés
https://aka.ms/ContentUserFeedback.
Hamarosan elérhető: 2024-ben fokozatosan kivezetjük a GitHub-problémákat a tartalom visszajelzési mechanizmusaként, és lecseréljük egy új visszajelzési rendszerre. További információ:Visszajelzés küldése és megtekintése a következőhöz: