Cette page vous a-t-elle été utile ?
Votre avis sur ce contenu est important. N'hésitez pas à nous faire part de vos commentaires.
Vous avez d'autres commentaires ?
1500 caractères restants
Exporter (0) Imprimer
Développer tout
Cet article a fait l'objet d'une traduction manuelle. Déplacez votre pointeur sur les phrases de l'article pour voir la version originale de ce texte. Informations supplémentaires.
Traduction
Source

Annuler les tâches Asynch restantes lorsque l'une d'elles est terminée (C# et Visual Basic)

À l'aide de la méthode Task.WhenAny et de CancellationToken, vous pouvez annuler toutes les tâches restantes lorsqu'une tâche est terminée. La méthode WhenAny accepte un argument qui est une collection de tâches. La méthode démarre toutes les tâches et retourne une seule tâche. La tâche unique est terminée lorsqu'une tâche de la collection est terminée.

Cet exemple montre comment utiliser un jeton d'annulation conjointement avec WhenAny pour rester dans la première tâche à finir de la collection de tâches et pour annuler les tâches restantes. Chaque tâche télécharge le contenu d'un site Web. L'exemple affiche la longueur du contenu du premier téléchargement à terminer et annule les autres téléchargements.

Remarque Remarque

Pour exécuter les exemples, Visual Studio 2012, Visual Studio 2013, Visual Studio Express 2012 pour Windows Desktop, Visual Studio Express 2013 pour Windows ou le .NET Framework 4.5 ou 4.5.1 doit être installé sur votre ordinateur.

Vous pouvez télécharger le projet Windows Presentation Foundation (WPF) complet à partir de Exemple async : réglage de votre application et suivre ces étapes.

  1. Décompressez le fichier que vous avez téléchargé, puis démarrez Visual Studio.

  2. Dans la barre de menus, sélectionnez Fichier, Ouvrir, Projet/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 solution (.sln) pour AsyncFineTuningCS ou AsyncFineTuningVB.

  4. Dans l'Explorateur de solutions, ouvrez le menu contextuel du projet CancelAfterOneTask, puis choisissez Définir comme projet de démarrage.

  5. Sélectionnez la touche F5 pour exécuter le projet.

    Appuyez sur les touches Ctrl + F5 pour exécuter le projet sans le déboguer.

  6. Exécutez le programme plusieurs fois pour vérifier que les différents téléchargements finissent en premier.

Si vous ne souhaitez pas télécharger le projet, vous pouvez examiner les fichiers complets MainWindow.xaml.vb et MainWindow.xaml.cs à la fin de cette rubrique.

L'exemple de cette rubrique ajoute au projet développé dans Annuler une tâche Asynch ou une liste de tâches (C# et Visual Basic) pour annuler une liste de tâches. L'exemple utilise la même interface, bien que le bouton Annuler ne soit pas utilisé explicitement.

Pour générer l'exemple vous-même, pas à pas, suivez les instructions de la section « Téléchargement de l'exemple », mais choisissez CancelAListOfTasks comme Projet de démarrage. Ajoutez les modifications de cette rubrique à ce projet.

Dans le fichier MainWindow.xaml.vb ou MainWindow.xaml.cs du projet CancelAListOfTasks, commencez la transition par déplacer les étapes de traitement pour chaque site Web à partir de la boucle dans AccessTheWebAsync vers la méthode async suivante.

// ***Bundle the processing steps for a website into one async method.
async Task<int> ProcessURLAsync(string url, HttpClient client, CancellationToken ct)
{
    // GetAsync returns a Task<HttpResponseMessage>. 
    HttpResponseMessage response = await client.GetAsync(url, ct);

    // Retrieve the website contents from the HttpResponseMessage. 
    byte[] urlContents = await response.Content.ReadAsByteArrayAsync();

    return urlContents.Length;
}

Dans AccessTheWebAsync, cet exemple utilise une requête, la méthode ToArray``1 et la méthode WhenAny pour créer et lancer un tableau de tâches. L'application de WhenAny au tableau retourne une tâche unique qui, une fois attendue, évalue la première tâche complétée dans le tableau de tâches.

Apportez les modifications suivantes dans AccessTheWebAsync. Les astérisques marquent les modifications du fichier de code.

  1. Commentez ou supprimez la boucle.

  2. Créer une requête qui, lorsqu'elle est exécutée, génère une collection de tâches génériques. Chaque appel à ProcessURLAsync retourne un TaskTResult est un entier.

    // ***Create a query that, when executed, returns a collection of tasks.
    IEnumerable<Task<int>> downloadTasksQuery =
        from url in urlList select ProcessURLAsync(url, client, ct);
    
  3. Appelez ToArray pour exécuter la requête et lancer les tâches. L'application de la méthode WhenAny dans l'étape suivante exécuterait la requête et commencerait les tâches sans utiliser ToArray, mais d'autres méthodes ne le peuvent pas. La pratique la plus sûre consiste à forcer l'exécution de la requête explicitement.

    // ***Use ToArray to execute the query and start the download tasks. 
    Task<int>[] downloadTasks = downloadTasksQuery.ToArray();
    
  4. Appelez WhenAny sur la collection de tâches. WhenAny retourne un Task(Of Task(Of Integer)) ou Task<Task<int>>. Autrement dit, WhenAny retourne une tâche qui correspond à une Task(Of Integer) unique ou une Task<int> lorsqu'elle est attendue. Cette tâche unique est la première tâche de la collection à se terminer. La tâche qui s'est terminée en premier est assignée à firstFinishedTask. Le type de firstFinishedTask est TaskTResult est un entier, car il s'agit du type de retour de ProcessURLAsync.

    // ***Call WhenAny and then await the result. The task that finishes  
    // first is assigned to firstFinishedTask.
    Task<int> firstFinishedTask = await Task.WhenAny(downloadTasks);
    
  5. Dans cet exemple, vous vous intéressez uniquement à la tâche qui se termine en premier. Par conséquent, utilisez CancellationTokenSource.Cancel pour annuler les tâches restantes.

    // ***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é.

    var length = await firstFinishedTask;
    resultsTextBox.Text += String.Format("\r\nLength of the downloaded website:  {0}\r\n", length);
    

Exécutez le programme plusieurs fois pour vérifier que les différents téléchargements finissent en premier.

Le code suivant est le fichier MainWindow.xaml.vb ou MainWindow.xaml.cs complet de l'exemple. Les astérisques marquent les éléments ajoutés pour cet exemple.

Notez que vous devez ajouter une référence pour System.Net.Http.

Vous pouvez télécharger le projet à partir de Exemple async : réglage de votre application.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

// Add a using directive and a reference for System.Net.Http. 
using System.Net.Http;

// Add the following using directive. 
using System.Threading;

namespace CancelAfterOneTask
{
    public partial class MainWindow : Window
    {
        // Declare a System.Threading.CancellationTokenSource.
        CancellationTokenSource cts;

        public MainWindow()
        {
            InitializeComponent();
        }


        private async void startButton_Click(object sender, RoutedEventArgs e)
        {
            // Instantiate the CancellationTokenSource.
            cts = new CancellationTokenSource();

            resultsTextBox.Clear();

            try
            {
                await AccessTheWebAsync(cts.Token);
                resultsTextBox.Text += "\r\nDownload complete.";
            }
            catch (OperationCanceledException)
            {
                resultsTextBox.Text += "\r\nDownload canceled.";
            }
            catch (Exception)
            {
                resultsTextBox.Text += "\r\nDownload failed.";
            }

            // Set the CancellationTokenSource to null when the download is complete.
            cts = null;
        }


        // You can still include a Cancel button if you want to. 
        private void cancelButton_Click(object sender, RoutedEventArgs e)
        {
            if (cts != null)
            {
                cts.Cancel();
            }
        }


        // Provide a parameter for the CancellationToken.
        async Task AccessTheWebAsync(CancellationToken ct)
        {
            HttpClient client = new HttpClient();

            // Call SetUpURLList to make a list of web addresses.
            List<string> urlList = SetUpURLList();

            // ***Comment out or delete the loop. 
            //foreach (var url in urlList) 
            //{ 
            //    // GetAsync returns a Task<HttpResponseMessage>.  
            //    // Argument ct carries the message if the Cancel button is chosen.  
            //    // ***Note that the Cancel button can cancel all remaining downloads. 
            //    HttpResponseMessage response = await client.GetAsync(url, ct); 

            //    // Retrieve the website contents from the HttpResponseMessage. 
            //    byte[] urlContents = await response.Content.ReadAsByteArrayAsync(); 

            //    resultsTextBox.Text += 
            //        String.Format("\r\nLength of the downloaded string: {0}.\r\n", urlContents.Length);
            //} 

            // ***Create a query that, when executed, returns a collection of tasks.
            IEnumerable<Task<int>> downloadTasksQuery =
                from url in urlList select ProcessURLAsync(url, client, ct);

            // ***Use ToArray to execute the query and start the download tasks. 
            Task<int>[] downloadTasks = downloadTasksQuery.ToArray();

            // ***Call WhenAny and then await the result. The task that finishes  
            // first is assigned to firstFinishedTask.
            Task<int> firstFinishedTask = 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. 
            var length = await firstFinishedTask;
            resultsTextBox.Text += String.Format("\r\nLength of the downloaded website:  {0}\r\n", length);
        }


        // ***Bundle the processing steps for a website into one async method.
        async Task<int> ProcessURLAsync(string url, HttpClient client, CancellationToken ct)
        {
            // GetAsync returns a Task<HttpResponseMessage>. 
            HttpResponseMessage response = await client.GetAsync(url, ct);

            // Retrieve the website contents from the HttpResponseMessage. 
            byte[] urlContents = await response.Content.ReadAsByteArrayAsync();

            return urlContents.Length;
        }


        // Add a method that creates a list of web addresses. 
        private List<string> SetUpURLList()
        {
            List<string> urls = new List<string> 
            { 
                "http://msdn.microsoft.com",
                "http://msdn.microsoft.com/en-us/library/hh290138.aspx",
                "http://msdn.microsoft.com/en-us/library/hh290140.aspx",
                "http://msdn.microsoft.com/en-us/library/dd470362.aspx",
                "http://msdn.microsoft.com/en-us/library/aa578028.aspx",
                "http://msdn.microsoft.com/en-us/library/ms404677.aspx",
                "http://msdn.microsoft.com/en-us/library/ff730837.aspx"
            };
            return urls;
        }
    }
    // Sample output: 

    // Length of the downloaded website:  158856 

    // Download complete.
}

Ajouts de la communauté

Afficher:
© 2015 Microsoft