Friday, April 13, 2012

C# 4.5 | Programmation asynchrone avec Framework. net 4.5


Contenu

- Opérations asynchrones
- Async - Modèle asynchrone des tâches
   Task et Task<IResult>
   async
   await
   Articles nécessaires pour utiliser Async
   Exemple d'utilisation avec async et await
 - Premier tutoriel: Création d'un logiciel synchrone
 - Deuxième tutoriel: Création d'un logiciel asynchrone

Les tâches asynchrones sont nécessaires lorsque les applications sont gelés en raison des actions qui ne finissent pas et ils ne laissent pas l'utilisateur de continuer à les utiliser, vous avez probablement vu le message "L'application ne répond ...". Voyons comment résoudre ce problème avec une nouvelle fonctionnalité du Framework 4.5.

Opérations asynchrones

Un ordinateur comporte un nombre fixe de processeurs et chacun de ces processeurs peuvent exécuter une seule opération à la fois. Appelons cette opération "thread". Chaque thread dans une application est programmé pour s'exécuter sur le processeur pour une période de temps.
Si un code effectue une action de I / O, le fil est suspendu jusqu'à ce que le dispositif a achevé ses travaux. Si vous avez une tâche très longtemps il peut commencer à travailler sur un thread séparé et obtenir le résultat de l'opération une fois que la tâche est terminée. Alors que le thread séparé qui exécute l'application peut effectuer d'autres tâches sans rapport avec la tâche de longue durée. Ainsi, nous pouvons isoler les tâches de travail.
La plupart des méthodes sont appelées synchrone, ce qui signifie que la méthode est terminée dans le thread en cours. Toutefois, certaines méthodes sont appelées asynchrones, ce qui signifie que le thread courant commence l'exécution de la méthode dans un autre thread et l'appel retourne immédiatement. Méthodes synchrones sont connus en tant que bloc, car le thread qui appelle la méthode fonctionne jusqu'à ce que d'autres la méthode complète.

Voici comment appeler une autre tâche à l'aide d'un
thread avec framework 2.0

namespace Threads
{
    class Program
    {
        static void Main(string[] args)
        {
            //Créer un thread qui commence par un appel à TacheLente
            System.Threading.Thread tache =
                new System.Threading.Thread(
                    new System.Threading.ParameterizedThreadStart(TacheLente));
            //Démarrer une autre tache
            tache.Start(900);
            //Demander si l'autre tâche est terminéea
            if (tache.ThreadState != System.Threading.ThreadState.Stopped)
                System.Console.WriteLine("L'autre tâche est en cours d'exécution");
            //Arrêter le thread en cours jusqu'à la fin d'une autre tâche ou
            //jusqu'à 1000 millisecondes
            tache.Join(1000);
            //Demandez à nouveau si la tâche est déjà terminé
            if (tache.ThreadState != System.Threading.ThreadState.Stopped)
                System.Console.WriteLine("On a passé une seconde, l'autre tâche continue");
            else
                System.Console.WriteLine("Enfin terminé une autre tâche!");
            System.Console.ReadLine();
        }

        /// <summary>
        /// Méthode avec une période égale au paramètre
        /// </summary>
        /// <param name="param"></param>
        static void TacheLente(object parametre)
        {
            //Paramètre comme un entier
            int periode = (int)parametre;
            //Arrêter la tâche par le temps indiqué
            System.Threading.Thread.Sleep(periode);
            System.Console.WriteLine("Achèvement de la tâche lente");
        }
    }
}


Pour plus d'informations sur les threads aller à::
http://msdn.microsoft.com/fr-fr/library/6kac2kdh.aspx
 
Modifications apportées aux données sont aussi des tâches qui durent longtemps, résultant en une mauvaise expérience. Une autre façon d'utiliser les tâches d'autres avec des threads est d'utiliser un objet BackgroundWorker comme indiqué ci-dessous.

namespace ExempleBackgroundWorker
{
    class Program
    {
        static void Main(string[] args)
        {
            //Créer un objet BackgroundWorker
            System.ComponentModel.BackgroundWorker tache=
                new System.ComponentModel.BackgroundWorker();
            //Méthode anonyme qui correspond à l'événement DoWork
            tache.DoWork += (o, parametres) =>
            {
                //Simuler un retard d'un seconde
                System.Threading.Thread.Sleep(1000);
                //Retourner quelque chose avec Result
                parametres.Result = System.DateTime.Now;
            };
            //Obtenir le valoir dans 'parametres'
            tache.RunWorkerCompleted += (o, parametres) =>
            {
                if (parametres.Error != null)
                {//Afficher un message d’erreur
                    System.Console.WriteLine("Erreur");
                }
                else
                {//Afficher un message de succès
                    System.Console.WriteLine("Sans erreurs");
                    //Imprimer le résultat
                    System.Console.WriteLine(parametres.Result.ToString());
                }

            };
            //Démarrer la tâche 
            tache.RunWorkerAsync();
            System.Console.ReadLine();
        }
    }
}


Il commence à sembler aussi compliqué, nous avons toujours besoin d'une méthode ou un bloc de code qui répond à des événements "DoWork" et "RunWorkerCompleted"

Async - Modèle asynchrone des tâches (TAP)

Si vous utilisez le modèle asynchrone des tâches du NET Framework 4.5 (TAP par son sigle en anglais) le méthode asynchrone retourne un objet Task qui représentant la tâche. Ce modèle utilise Task et Task<TResult> dans l'espace de noms System.Threading.Tasks pour représenter les opérations asynchrones arbitraires.   
Lors de l'appel d'une tâche et son achèvement est prévu, vous utilisez le mot "await" sous la forme:

await maMethodeAsync();
Cela ne modifie pas le flux d'exécution, ni est là pour accrocher des méthodes à des événements, encore plus, il n'y a pas d'événements pour gérer parce que maintenant le compilateur est responsable de leur création.

Task et Task<IResult>

Le type de retour d'une méthode asynchrone doit être void, Task ou Task<T>. Le type de retour d'une méthode anonyme est le type retourné par 'return' (si il ya un 'return') du délégué.

Dans un méthode asynchrone avec type de retour void ou de travail, les déclarations de retour ne doit pas avoir une expression.

Lorsque le type de retour est Task<T>, les déclarations de retour doit avoir une expression qui est implicitement convertible en T.

async

Classiquement méthodes asynchrones utilisent le suffixe Async pour indiquer que l'exécution peut être effectuée qu'après que la méthode que vous appelez a pris fin.

Une méthode asynchrone fournit un moyen pratique de faire des choses qui prennent beaucoup de temps sans causer des blocages dans le thread appelant. Le thread qui appelle une méthode asynchrone peut continuer sans attendre que la méthode async est terminée.

await

Une expression await n'est autorisée que dans une méthode de façon asynchrone. Généralement, une méthode modifiée pour le modificateur async contient au moins une expression await. Une telle méthode s'exécute de façon synchrone jusqu'à ce qu'il rencontre la première expression await, au cours de laquelle l'exécution est suspendue jusqu'à ce que la tâche est terminée.


Articles nécessaires pour utiliser Async

Async est disponible dans la version bêta de Visual Studio 11, ou au téléchargement CTP (Community Technology Preview) de Visual Studio 2010 SP1..

Exemple d'utilisation asynchrone avec asycn et await

Comme un petit exemple pour comprendre comment vous pouvez utiliser async et await, nous allons générer un projet WPF qui nous permettra de voir l'effet de modèle TAP

Premier exercice: Création d'une application de manière synchrone.

1.      Démarrez Visual Studio 11 et créé une nouvelle application WPF en C # appelé ExempleAsynn.
2.      Modifiez les propriétés de la fenêtre principale d'avoir une taille de 480 par 480 pixels.
3.      Ajoutez deux boutons et une ListBox. Attribuer des noms aux boutons, BoutonLire et BoutonMessage respectivement. Attribuer du nom a la Listbox ListeDesFichiers.
4.      Disposez les composants afin qu'ils aient l'apparence suivante:




5.      Ouvrez le fichier de code en C# MainWindow associée à MainWindox.xaml.cs et ajoutez la ligne suivante juste en dessous de la méthode constructeur.

        private IEnumerable<string> RecupererDesFichiers()
        {
            var fichiers = from fichier in
System.IO.Directory.GetFiles(
@"C:\Windows\System32")
              select fichier;

            System.Threading.Thread.Sleep(5000);
            return fichiers;
        }

6.       Double-cliquez sur le bouton BoutonLire pour créer la méthode, ajoutez le code suivant:

        private void BoutonLire_Click(object sender, RoutedEventArgs e)
        {
            BoutonLeer.IsEnabled = false;
            ListeDesFichiers.ItemsSource = RecupererDesFichiers();
            BoutonLeer.IsEnabled = true;
        }

7.      Maintenant, retournez à «MainWindow.xaml» et double-cliquez sur BoutonMessage pour générer le gestionnaire d'événements Click. Ensuite, ajoutez le code suivant.


        private void BoutonMessage_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("L'heure exacte: " +
DateTime.Now.ToLongTimeString());
        }


8.      Exécutez l'application et appuyez sur le bouton. Notez que l'application s'arrête et vous ne pouvez pas appuyer sur le bouton Message. Après 5 secondes, le ListBox est rempli avec les noms de fichiers et ​​le bouton Message est fonctionnel. On voit également le message.



Deuxième exercice: Création de l'application asynchrone

1.      Allez au contenu de la méthode RecupererDesFichiers, modifiez sa structure de sorte que le type de données pour retourner change de IEnumerable<String> à Task<IEnumerable<String>> et le nom de la méthode a maintenant le suffixe «Async» comme le montre. N'oubliez pas de déclarer l'espace de noms System.Threading.Tasks.

private Task<IEnumerable<string>> RecupererDesFichiersAsync()


2.      Maintenant, mettez le code de la méthode dans une tâche, pour retourner un objet de type de tâche.

        private Task<IEnumerable<string>> RecupererDesFichiersAsync()
        {
            return Task.Run(() =>
            {
                System.Threading.Thread.Sleep(5000);
                var fichiers = from fichier in
System.IO.Directory.GetFiles(@"C:\Windows\System32")
select fichier;
                return fichiers;
            });
        }


1.      Changez la structure de la méthode en ajoutant le modificateur async pour BoutonLire_Click comme le montre.

   private async void BoutonLire_Click(object sender, RoutedEventArgs e)

.
2.      Maintenant modifiez l'appel de méthode, de sorte se fait maintenant par le biais d'un appel asynchrone à l'aide du mot réservé "await" comme un modificateur. Rappelez-vous que nous avons déjà changé le nom de la méthode en ajoutant le suffixe du "Async".

ListeDesFichiers.ItemsSource = await RecupererDesFichiersAsync();

3.      Démarrez le programme, appuyez sur le bouton "Fichiers" et vérifiez que l'application n'est pas arrêtée et est sensible et qu'il est maintenant possible d'appuyer sur le bouton Message sans attendre la fin de la période de 5 secondes.



Dans ce deuxième exemple, nous avons créé une application qui ne s'arrête pas son fonctionnement pour initier un appel à une méthode.

Références:


No comments: