Exporter (0) Imprimer
Développer tout
Cet article a fait l'objet d'une traduction automatique. Déplacez votre pointeur sur les phrases de l'article pour voir la version originale de ce texte. Informations supplémentaires.
Traduction
Source

Démarrer plusieurs tâches Asynch et les traiter une fois terminées (C# et Visual Basic)

À l'aide de Task.WhenAny, vous pouvez démarrer plusieurs tâches en même temps et les traiter une par une lorsqu'elles sont terminées, plutôt que de les traiter dans l'ordre dans lequel elles ont démarré.

L'exemple suivant utilise une requête pour créer une collection de tâches. Chaque tâche télécharge le contenu d'un site Web spécifié. Dans chaque itération d'une boucle while, un appel attendu à WhenAny retourne la tâche de la collection de tâches qui termine son téléchargement en premier. Cette tâche est supprimée de la collection et traitée. La boucle se répète jusqu'à ce que la collection ne contienne plus de tâches.

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 ProcessTasksAsTheyFinish, 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 projet plusieurs fois pour vérifier que les longueurs téléchargées n'apparaissent pas toujours dans le même ordre.

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.

Cet exemple ajoute au code développé dans Annuler les tâches Asynch restantes lorsque l'une d'elles est terminée (C# et Visual Basic) et utilise la même interface utilisateur.

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 CancelAfterOneTask comme Projet de démarrage. Ajoutez les modifications de cette rubrique à la méthode AccessTheWebAsync dans ce projet. Les modifications sont marquées avec des astérisques.

Le projet CancelAfterOneTask inclut déjà une requête qui, une fois exécutée, crée une collection de tâches. Chaque appel à ProcessURLAsync dans le code suivant retourne Task<TResult>TResult est un entier.


IEnumerable<Task<int>> downloadTasksQuery =
    from url in urlList select ProcessURL(url, client, ct);


Dans le fichier MainWindow.xaml.vb ou MainWindow.xaml.cs du projet, apportez les modifications suivantes à la méthode AccessTheWebAsync.

  • Exécutez la requête en appliquant Enumerable.ToList<TSource> au lieu de ToArray<TSource>.

    
    List<Task<int>> downloadTasks = downloadTasksQuery.ToList();
    
    
    
  • Ajoutez une boucle while qui exécute les étapes suivantes pour chaque tâche de la collection.

    1. Attend un appel à WhenAny pour identifier la première tâche de la collection à terminer son téléchargement.

      
      Task<int> firstFinishedTask = await Task.WhenAny(downloadTasks);
      
      
      
    2. Supprime cette tâche de la collection.

      
      downloadTasks.Remove(firstFinishedTask);
      
      
      
    3. Attend firstFinishedTask, qui est retourné par un appel à ProcessURLAsync. La variable firstFinishedTask est un Task<TResult>TReturn est un entier. La tâche est déjà terminée, mais vous attendez qu'elle récupère la longueur du site Web téléchargé, comme indiqué dans l'exemple suivant.

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

Vous devriez exécuter le projet plusieurs fois pour vérifier que les longueurs téléchargées n'apparaissent pas toujours dans le même ordre.

Mise en garde Attention

L'utilisation de WhenAny dans une boucle, comme décrit dans l'exemple, est parfaite pour résoudre des problèmes qui impliquent un petit nombre de tâches. Toutefois, d'autres approches sont plus efficaces si vous avez un grand nombre de tâches à traiter. Pour plus d'informations et pour découvrir des exemples, consultez Traitement des résultats des tâches qui se terminent.

Le code suivant est le texte complet du fichier MainWindow.xaml.vb ou MainWindow.xaml.cs 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 ProcessTasksAsTheyFinish
{
    public partial class MainWindow : Window
    {
        // Declare a System.Threading.CancellationTokenSource.
        CancellationTokenSource cts;

        public MainWindow()
        {
            InitializeComponent();
        }

        private async void startButton_Click(object sender, RoutedEventArgs e)
        {
            resultsTextBox.Clear();

            // Instantiate the CancellationTokenSource.
            cts = new CancellationTokenSource();

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

            cts = null;
        }


        private void cancelButton_Click(object sender, RoutedEventArgs e)
        {
            if (cts != null)
            {
                cts.Cancel();
            }
        }


        async Task AccessTheWebAsync(CancellationToken ct)
        {
            HttpClient client = new HttpClient();

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

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

            // ***Use ToList to execute the query and start the tasks. 
            List<Task<int>> downloadTasks = 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.
                    Task<int> firstFinishedTask = await Task.WhenAny(downloadTasks);

                    // ***Remove the selected task from the list so that you don't
                    // process it more than once.
                    downloadTasks.Remove(firstFinishedTask);

                    // Await the completed task.
                    int length = await firstFinishedTask;
                    resultsTextBox.Text += String.Format("\r\nLength of the download:  {0}", length);
            }
        }


        private List<string> SetUpURLList()
        {
            List<string> urls = new List<string> 
            { 
                "http://msdn.microsoft.com",
                "http://msdn.microsoft.com/library/windows/apps/br211380.aspx",
                "http://msdn.microsoft.com/en-us/library/hh290136.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;
        }


        async Task<int> ProcessURL(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;
        }
    }
}

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


Ajouts de la communauté

AJOUTER
Microsoft réalise une enquête en ligne pour recueillir votre opinion sur le site Web de MSDN. Si vous choisissez d’y participer, cette enquête en ligne vous sera présentée lorsque vous quitterez le site Web de MSDN.

Si vous souhaitez y participer,
Afficher:
© 2014 Microsoft