Developpez.com - Rubrique .NET

Le Club des Développeurs et IT Pro

Apprendre à programmer avec les pools de threads en C# - Deuxième partie : chaînage et fabrique de tâches

Un tutoriel de François Dorin

Le 2016-10-13 08:33:44, par François DORIN, Expert éminent sénior
Bonjour à toutes et à tous,

Je vous propose le second tutoriel de la série pour apprendre l'utilisation du pool de threads en programmation C#. Vous pouvez le consulter à l'adresse suivante : http://fdorin.developpez.com/tutorie...eadpool/part2/

Bonne lecture, et n'hésitez pas à apporter vos commentaires

Retrouvez les meilleurs et tutoriels pour apprendre la programmation C#
  Discussion forum
38 commentaires
  • ebastien
    Membre expérimenté
    Bonjour,

    Très bon tutoriel et comme à chaque fois, clair et précis. On sent la maîtrise du sujet...
  • François DORIN
    Expert éminent sénior
    Bonjour à toutes et à tous,

    Je vous propose le troisième tutoriel de la série pour apprendre l'utilisation du pool de threads en programmation C#. Vous pouvez le consulter à l'adresse suivante : http://fdorin.developpez.com/tutorie...eadpool/part3/

    Au programme, l'utilisation des mots-clés async et await.

    Bonne lecture, et n'hésitez pas à apporter vos commentaires

    Retrouvez les meilleurs et tutoriels pour apprendre la programmation C#
  • stailer
    Membre chevronné
    Merci pour cet article,

    En faisant des tests sur ma classe qui gère une suite de tâche je me suis aperçu que dans certains contextes mon application (une Winform et une autre Wpf) pouvait bloquer en attendant la fin.
    J'ai donc pu modifier et corriger le problème.

    Cet article est très concret sans blabla théorique inutile. Beau travail.
  • Community Management
    Community Manager
    Merci Dorinf et félicitations pour cette deuxième partie
  • lutecefalco
    Rédacteur
    Hmmm, je ne suis pas d'accord.
    Pour moi, le await/async ne fait que "libérer" le thread courant pour faire autre chose et l'async est géré sur ce même thread lors du "call back"
  • lutecefalco
    Rédacteur
    Ouais mais là tu triches en passant par Task.Run
    Si tu reprends ton exemple de code:

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    static void Main(string[] args)        {
                Console.WriteLine(DateTime.Now.ToString("HH:mm.ss"));
                var t = Async3Times();
                t.Wait();
    
    
                Console.WriteLine(DateTime.Now.ToString("HH:mm.ss"));
                Console.ReadLine();
            }
    
    private async static Task Async3Times()
            {
                await HelloWorldAsync();
                await HelloWorldAsync();
                await HelloWorldAsync();
            }
    Là on attend 12 secondes.
    S'il y avait eu création de threads différents et donc exécution en parallèle, ça aurait pris 4 secondes.
    Ou alors j'ai zappé un truc, c'est pas trop mon domaine ça
  • François DORIN
    Expert éminent sénior
    Envoyé par lutecefalco
    Ouais mais là tu triches en passant par Task.Run
    Aucune tricherie. Où il faut que tu m'expliques pourquoi. await attend une instance de Task. Je lui en fournie une.

    Envoyé par lutecefalco

    Si tu reprends ton exemple de code:

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    static void Main(string[] args)        {
                Console.WriteLine(DateTime.Now.ToString("HH:mm.ss"));
                var t = Async3Times();
                t.Wait();
    
    
                Console.WriteLine(DateTime.Now.ToString("HH:mm.ss"));
                Console.ReadLine();
            }
    
    private async static Task Async3Times()
            {
                await HelloWorldAsync();
                await HelloWorldAsync();
                await HelloWorldAsync();
            }
    Là on attend 12 secondes.
    S'il y avait eu création de threads différents et donc exécution en parallèle, ça aurait pris 4 secondes.
    Ou alors j'ai zappé un truc, c'est pas trop mon domaine ça
    Tu as effectivement zappé un truc. Que ton programme s'exécute parallèlement ou séquentiellement n'a aucune incidence ici. Pourquoi ? Car ta méthode Async3Times n'appelle pas 3 fois HelloWordAsync de manière parallèle mais de manière séquentielle. Il l'appelle une première fois et attend la fin de son exécution. Puis, l'appelle une seconde fois et attend la fin de son exécution, avant de l'appeler une troisième fois et d'attendre la fin de son exécution.

    Ce qui s'exécute en parallèle dans ton code, c'est la méthode Async3Times qui s'exécute en parallèle de la méthode Main, et l'exécution des méthodes HelloWorldAsync qui s'exécute également sur un autre thread (qui potentiellement peut être le même que celui exécutant Async3Times car lorsque Async3Times est en attente sur un await, il libère le thread l'exécutant).

    Le point important, c'est que lorsqu'une tâche est en attente d'une autre sur un await, elle libère le thread exécutant la tâche, au lieu de le bloquer comme le font les méthodes classiques. Pourquoi est-ce important ? Une des raisons justifiant l'introduction de ce concept async/await est de permettre l'écriture quasiment sans modification (juste le mot clé await à rajouter !), dans le thread graphique, de méthodes longues (attendant une communication réseau par exemple) qui ne bloquent pas l'interface graphique.
  • François DORIN
    Expert éminent sénior
    Merci !

    Maintenant, il faut que je trouve le temps de finir le 3ème volet
  • lutecefalco
    Rédacteur
    Merci pour le tuto.
    Ptite question: le CancellationToken.Cancel(), il ne faut pas plutôt le faire quand la tâche retourne true?
    (Ou alors j'ai lu trop vite )
  • François DORIN
    Expert éminent sénior
    Envoyé par lutecefalco
    Ptite question: le CancellationToken.Cancel(), il ne faut pas plutôt le faire quand la tâche retourne true?
    Non, c'est bien quand la tâche retourne false. Si la tâche retourne false, c'est que le nombre n'est pas premier car on a trouvé un diviseur. On peut donc arrêter tous les autres calculs.

    Si maintenant la tâche retourne true, c'est qu'il n'y a pas de diviseur dans un intervalle donné. Mais il peut potentiellement y en avoir dans d'autres intervalles. On ne doit donc pas interrompre les autres tâches. Est-ce plus clair ainsi ?