Dela via


Starta flera asynkrona uppgifter och bearbeta dem när de har slutförts (Visual Basic)

Med hjälp Task.WhenAnyav kan du starta flera uppgifter samtidigt och bearbeta dem en i taget när de har slutförts i stället för att bearbeta dem i den ordning de startas.

I följande exempel används en fråga för att skapa en samling uppgifter. Varje uppgift laddar ned innehållet på en angiven webbplats. I varje iteration av en while-loop returnerar ett inväntat anrop för att WhenAny returnera uppgiften i samlingen med uppgifter som slutför nedladdningen först. Den uppgiften tas bort från samlingen och bearbetas. Loopen upprepas tills samlingen inte innehåller några fler uppgifter.

Kommentar

Om du vill köra exemplen måste du ha Visual Studio 2012 eller senare och .NET Framework 4.5 eller senare installerat på datorn.

Ladda ned exemplet

Du kan ladda ned hela WPF-projektet (Windows Presentation Foundation) från Async Sample: Fine Tuning Your Application och sedan följa dessa steg.

  1. Expandera filen som du laddade ned och starta sedan Visual Studio.

  2. På menyraden väljer du Arkiv, Öppna, Projekt/Lösning.

  3. I dialogrutan Öppna projekt öppnar du mappen som innehåller exempelkoden som du dekomprimerade och öppnar sedan lösningsfilen (.sln) för AsyncFineTuningVB.

  4. I Solution Explorer öppnar du snabbmenyn för projektet ProcessTasksAsTheyFinish och väljer sedan Ange som startprojekt.

  5. Välj F5-nyckeln för att köra projektet.

    Välj Ctrl+F5-tangenterna för att köra projektet utan att felsöka det.

  6. Kör projektet flera gånger för att kontrollera att de nedladdade längderna inte alltid visas i samma ordning.

Om du inte vill ladda ned projektet kan du granska filen MainWindow.xaml.vb i slutet av det här avsnittet.

Skapa exemplet

Det här exemplet lägger till i koden som har utvecklats i Avbryt återstående Async-uppgifter efter att One Is Complete (Visual Basic) och använder samma användargränssnitt.

Om du vill skapa exemplet själv följer du anvisningarna i avsnittet "Ladda ned exemplet" steg för steg, men väljer AvbrytEfterOneTask som StartUp-projekt. Lägg till ändringarna i det här avsnittet AccessTheWebAsync i metoden i projektet. Ändringarna markeras med asterisker.

Projektet CancelAfterOneTask innehåller redan en fråga som, när det körs, skapar en samling uppgifter. Varje anrop till ProcessURLAsync i följande kod returnerar ett Task<TResult> var TResult är ett heltal.

Dim downloadTasksQuery As IEnumerable(Of Task(Of Integer)) =  
    From url In urlList Select ProcessURLAsync(url, client, ct)  

I den MainWindow.xaml.vb filen i projektet gör du följande ändringar i AccessTheWebAsync metoden.

  • Kör frågan genom att tillämpa Enumerable.ToList i stället för ToArray.

    Dim downloadTasks As List(Of Task(Of Integer)) = downloadTasksQuery.ToList()  
    
  • Lägg till en while-loop som utför följande steg för varje uppgift i samlingen.

    1. Väntar på ett anrop till för att WhenAny identifiera den första uppgiften i samlingen för att slutföra nedladdningen.

      Dim finishedTask As Task(Of Integer) = Await Task.WhenAny(downloadTasks)  
      
    2. Tar bort uppgiften från samlingen.

      downloadTasks.Remove(finishedTask)  
      
    3. Awaits finishedTask, som returneras av ett anrop till ProcessURLAsync. Variabeln finishedTask är en Task<TResult> var TReturn är ett heltal. Uppgiften är redan klar, men du väntar på att den ska hämta längden på den nedladdade webbplatsen, vilket visas i följande exempel.

      Dim length = Await finishedTask  
      resultsTextBox.Text &= String.Format(vbCrLf & "Length of the downloaded website:  {0}" & vbCrLf, length)  
      

Du bör köra projektet flera gånger för att kontrollera att de nedladdade längderna inte alltid visas i samma ordning.

Varning

Du kan använda WhenAny i en loop, enligt beskrivningen i exemplet, för att lösa problem som omfattar ett litet antal uppgifter. Andra metoder är dock mer effektiva om du har ett stort antal uppgifter att bearbeta. Mer information och exempel finns i Bearbeta uppgifter när de slutförs.

Fullständigt exempel

Följande kod är den fullständiga texten i MainWindow.xaml.vb-filen för exemplet. Asterisker markerar de element som lades till i det här exemplet.

Observera att du måste lägga till en referens för System.Net.Http.

Du kan ladda ned projektet från Async Sample: Finjustering av ditt program.

' 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 finishedTask 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(finishedTask)  
  
            ' ***Await the first completed task and display the results.  
            Dim length = Await finishedTask  
            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/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 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.  

Se även