Annuler les tâches Asynch restantes lorsque l’une d’elles est terminée (Visual Basic)Cancel Remaining Async Tasks after One Is Complete (Visual Basic)

Utilisez la méthode Task.WhenAny avec un CancellationToken pour annuler toutes les tâches restantes quand une tâche est terminée.By using the Task.WhenAny method together with a CancellationToken, you can cancel all remaining tasks when one task is complete. La méthode WhenAny accepte un argument qui est une collection de tâches.The WhenAny method takes an argument that’s a collection of tasks. La méthode démarre toutes les tâches et retourne une tâche unique.The method starts all the tasks and returns a single task. Cette dernière est terminée une fois que toutes les tâches de la collection sont terminées.The single task is complete when any task in the collection is complete.

Cet exemple montre comment utiliser un jeton d’annulation avec WhenAny pour attendre la fin de la première tâche de la collection et annuler les tâches restantes.This example demonstrates how to use a cancellation token in conjunction with WhenAny to hold onto the first task to finish from the collection of tasks and to cancel the remaining tasks. Chaque tâche télécharge le contenu d’un site web.Each task downloads the contents of a website. L’exemple affiche la longueur du contenu du premier téléchargement terminé et annule les autres téléchargements.The example displays the length of the contents of the first download to complete and cancels the other downloads.

Notes

Pour exécuter les exemples, Visual Studio version 2012 ou ultérieure et le .NET Framework version 4.5 ou ultérieure doivent être installés sur votre ordinateur.To run the examples, you must have Visual Studio 2012 or newer and the .NET Framework 4.5 or newer installed on your computer.

Téléchargement de l'exempleDownloading the Example

Téléchargez l’intégralité du projet Windows Presentation Foundation (WPF) à partir de la page Exemple Async : réglage de votre application, puis procédez comme suit.You can download the complete Windows Presentation Foundation (WPF) project from Async Sample: Fine Tuning Your Application and then follow these steps.

  1. Décompressez le fichier que vous avez téléchargé, puis démarrez Visual Studio.Decompress the file that you downloaded, and then start Visual Studio.

  2. Dans la barre de menus, choisissez Fichier, Ouvrir, Projet/Solution.On the menu bar, choose File, Open, Project/Solution.

  3. Dans la boîte de dialogue Ouvrir le projet, ouvrez le dossier contenant l’exemple de code que vous avez décompressé, puis ouvrez le fichier de solution (.sln) pour AsyncFineTuningVB.In the Open Project dialog box, open the folder that holds the sample code that you decompressed, and then open the solution (.sln) file for AsyncFineTuningVB.

  4. Dans l’Explorateur de solutions, ouvrez le menu contextuel du projet CancelAfterOneTask, puis choisissez Définir comme projet de démarrage.In Solution Explorer, open the shortcut menu for the CancelAfterOneTask project, and then choose Set as StartUp Project.

  5. Appuyez sur la touche F5 pour exécuter le projet.Choose the F5 key to run the project.

    Appuyez sur les touches Ctrl+F5 pour exécuter le projet sans le déboguer.Choose the Ctrl+F5 keys to run the project without debugging it.

  6. Exécutez le programme plusieurs fois pour vérifier que différents téléchargements se terminent en premier.Run the program several times to verify that different downloads finish first.

Si vous ne souhaitez pas télécharger le projet, vous pouvez passer en revue le fichier MainWindow.xaml.vb à la fin de cette rubrique.If you don't want to download the project, you can review the MainWindow.xaml.vb file at the end of this topic.

Génération de l’exempleBuilding the Example

L’exemple de cette rubrique ajoute au projet développé dans annuler une tâche asynchrone ou une liste de tâches pour annuler une liste de tâches.The example in this topic adds to the project that's developed in Cancel an Async Task or a List of Tasks to cancel a list of tasks. Il utilise la même interface utilisateur, bien que le bouton Annuler ne soit pas utilisé explicitement.The example uses the same UI, although the Cancel button isn’t used explicitly.

Pour générer vous-même l’exemple, suivez les instructions pas à pas de la section « Téléchargement de l’exemple », mais choisissez CancelAListOfTasks comme Projet de démarrage.To build the example yourself, step by step, follow the instructions in the "Downloading the Example" section, but choose CancelAListOfTasks as the StartUp Project. Ajoutez les changements de cette rubrique à ce projet.Add the changes in this topic to that project.

Dans le fichier MainWindow. Xaml. vb du projet CancelAListOfTasks , commencez la transition en déplaçant les étapes de traitement de chaque site Web de la boucle dans AccessTheWebAsync vers la méthode Async suivante.In the MainWindow.xaml.vb file of the CancelAListOfTasks project, start the transition by moving the processing steps for each website from the loop in AccessTheWebAsync to the following async method.

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

Dans AccessTheWebAsync, cet exemple utilise une requête, la méthode ToArray et la méthode WhenAny pour créer et démarrer un tableau de tâches.In AccessTheWebAsync, this example uses a query, the ToArray method, and the WhenAny method to create and start an array of tasks. L’application de WhenAny au tableau retourne une tâche unique qui, quand elle est attendue, prend la valeur de la première tâche terminée dans le tableau de tâches.The application of WhenAny to the array returns a single task that, when awaited, evaluates to the first task to reach completion in the array of tasks.

Dans AccessTheWebAsync, effectuez les changements suivants.Make the following changes in AccessTheWebAsync. Les astérisques signalent les changements dans le fichier de code.Asterisks mark the changes in the code file.

  1. Commentez ou supprimez la boucle.Comment out or delete the loop.

  2. Créer une requête qui, une fois exécutée, génère une collection de tâches génériques.Create a query that, when executed, produces a collection of generic tasks. Chaque appel à ProcessURLAsync retourne un Task<TResult>TResult est un entier.Each call to ProcessURLAsync returns a Task<TResult> where TResult is an integer.

    ' ***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. Appelez ToArray pour exécuter la requête et démarrer les tâches.Call ToArray to execute the query and start the tasks. L’application de la méthode WhenAny à l’étape suivante exécute la requête et démarre les tâches sans utiliser ToArray, mais il se peut que d’autres méthodes n’y parviennent pas.The application of the WhenAny method in the next step would execute the query and start the tasks without using ToArray, but other methods might not. L’approche la plus sûre consiste à forcer l’exécution de la requête de manière explicite.The safest practice is to force execution of the query explicitly.

    ' ***Use ToArray to execute the query and start the download tasks.
    Dim downloadTasks As Task(Of Integer)() = downloadTasksQuery.ToArray()
    
  4. Appelez WhenAny sur la collection de tâches.Call WhenAny on the collection of tasks. WhenAny retourne Task(Of Task(Of Integer)) ou Task<Task<int>>.WhenAny returns a Task(Of Task(Of Integer)) or Task<Task<int>>. Autrement dit, WhenAny retourne une tâche qui prend la valeur d’un Task(Of Integer) ou Task<int> unique quand elle est attendue.That is, WhenAny returns a task that evaluates to a single Task(Of Integer) or Task<int> when it’s awaited. Cette tâche unique est la première tâche de la collection à se terminer.That single task is the first task in the collection to finish. La tâche terminée en premier est assignée à firstFinishedTask.The task that finished first is assigned to firstFinishedTask. Le type de firstFinishedTask est Task<TResult>, où TResult est un entier car il s’agit du type de retour de ProcessURLAsync.The type of firstFinishedTask is Task<TResult> where TResult is an integer because that's the return type of ProcessURLAsync.

    ' ***Call WhenAny and then await the result. The task that finishes
    ' first is assigned to firstFinishedTask.
    Dim firstFinishedTask As Task(Of Integer) = Await Task.WhenAny(downloadTasks)
    
  5. Dans cet exemple, vous vous intéressez uniquement à la tâche qui se termine en premier.In this example, you’re interested only in the task that finishes first. Par conséquent, utilisez CancellationTokenSource.Cancel pour annuler les tâches restantes.Therefore, use CancellationTokenSource.Cancel to cancel the remaining tasks.

    ' ***Cancel the rest of the downloads. You just want the first one.
    cts.Cancel()
    
  6. Enfin, attendez firstFinishedTask pour récupérer la longueur du contenu téléchargé.Finally, await firstFinishedTask to retrieve the length of the downloaded content.

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

Exécutez le programme plusieurs fois pour vérifier que différents téléchargements se terminent en premier.Run the program several times to verify that different downloads finish first.

Exemple completComplete Example

Le code suivant est le fichier MainWindow. Xaml. vb ou MainWindow.xaml.cs complet pour l’exemple.The following code is the complete MainWindow.xaml.vb or MainWindow.xaml.cs file for the example. Des astérisques marquent les éléments ajoutés pour cet exemple.Asterisks mark the elements that were added for this example.

Notez que vous devez ajouter une référence pour System.Net.Http.Notice that you must add a reference for System.Net.Http.

Vous pouvez télécharger le projet à partir de la page Exemple Async : réglage de votre application.You can download the project from Async Sample: Fine Tuning Your Application.

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

Voir aussiSee also