Sdílet prostřednictvím


Spuštění několika asynchronních úloh a jejich zpracování při jejich dokončení (Visual Basic)

Pomocí nich Task.WhenAnymůžete současně spouštět více úkolů a zpracovávat je po jednom, protože jsou dokončené, a ne je zpracovávat v pořadí, ve kterém jsou spuštěné.

Následující příklad používá dotaz k vytvoření kolekce úloh. Každý úkol stáhne obsah zadaného webu. V každé iteraci smyčky while vrátí očekávané volání WhenAny úkolu v kolekci úkolů, které dokončí její stahování jako první. Tato úloha se odebere z kolekce a zpracuje se. Smyčka se opakuje, dokud kolekce neobsahuje žádné další úkoly.

Poznámka:

Abyste mohli spustit příklady, musíte mít na počítači nainstalovanou sadu Visual Studio 2012 nebo novější a rozhraní .NET Framework 4.5 nebo novější.

Stažení příkladu

Kompletní projekt Windows Presentation Foundation (WPF) si můžete stáhnout z asynchronní ukázky: Vyladění aplikace a pak postupujte podle těchto kroků.

  1. Dekomprimujte soubor, který jste stáhli, a spusťte Visual Studio.

  2. Na řádku nabídek zvolte Soubor, Otevřít, Projekt nebo Řešení.

  3. V dialogovém okně Otevřít projekt otevřete složku obsahující ukázkový kód, který jste dekomprimovali, a pak otevřete soubor řešení (.sln) pro AsyncFineTuningVB.

  4. V Průzkumník řešení otevřete místní nabídku projektu ProcessTasksAsTheyFinish a pak zvolte Nastavit jako spouštěcí projekt.

  5. Zvolte klávesu F5, aby se projekt spustil.

    Pokud chcete projekt spustit bez ladění, zvolte klávesy Ctrl+F5.

  6. Spusťte projekt několikrát, abyste ověřili, že se stažené délky nezobrazují vždy ve stejném pořadí.

Pokud si projekt nechcete stáhnout, můžete si projít MainWindow.xaml.vb soubor na konci tohoto tématu.

Sestavení příkladu

Tento příklad přidá kód vyvinutý ve funkci Zrušit zbývající asynchronní úlohy po dokončení jednoho (Visual Basic) a použije stejné uživatelské rozhraní.

Pokud chcete sestavit příklad sami, postupujte krok za krokem podle pokynů v části "Stažení příkladu", ale jako projekt StartUp zvolte CancelAfterOneTask. Přidejte změny v tomto tématu do AccessTheWebAsync metody v tomto projektu. Změny jsou označené hvězdičkami.

Projekt CancelAfterOneTask již obsahuje dotaz, který při spuštění vytvoří kolekci úkolů. Každé volání ProcessURLAsync v následujícím kódu vrátí Task<TResult> celé TResult číslo.

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

V MainWindow.xaml.vb souboru projektu proveďte následující změny metody AccessTheWebAsync .

  • Spusťte dotaz tak, že použijete Enumerable.ToList místo ToArray.

    Dim downloadTasks As List(Of Task(Of Integer)) = downloadTasksQuery.ToList()  
    
  • Přidejte smyčku While, která provádí následující kroky pro každou úlohu v kolekci.

    1. Čeká na volání k WhenAny identifikaci prvního úkolu v kolekci, aby se dokončilo stahování.

      Dim finishedTask As Task(Of Integer) = Await Task.WhenAny(downloadTasks)  
      
    2. Odebere danou úlohu z kolekce.

      downloadTasks.Remove(finishedTask)  
      
    3. Awaits finishedTask, který je vrácen voláním ProcessURLAsync. Proměnná finishedTask je celé Task<TResult>TReturn číslo. Úkol je již dokončený, ale očekáváte, že načte délku staženého webu, jak ukazuje následující příklad.

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

Projekt byste měli spustit několikrát, abyste ověřili, že se stažené délky nezobrazí vždy ve stejném pořadí.

Upozornění

Ve smyčce, jak je popsáno v příkladu, můžete použít WhenAny k řešení problémů, které zahrnují malý počet úkolů. Pokud ale máte velký počet úkolů ke zpracování, jsou další přístupy efektivnější. Další informace a příklady najdete v tématu Zpracování úloh při jejich dokončení.

Kompletní příklad

Následující kód je úplný text souboru MainWindow.xaml.vb příkladu. Hvězdičky označují prvky přidané v tomto příkladu.

Všimněte si, že je nutné přidat odkaz pro System.Net.Http.

Projekt si můžete stáhnout z asynchronní ukázky: Vyladění aplikace.

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

Viz také