Les pc modernes sont capables de lancer plusieurs traitements en parallèle. Il serait dommage que les applications que nous développons n’en soient pas capables. Le Framework .NET propose de nombreuses classes pour pouvoir lancer plusieurs tâches simultanées. Petit tour d’horizon du multithreading en c#…

La classe thread

C’est la plus connue des classes pour faire du multithreading. Elle se trouve dans l’espace de nom System.Threading. Cette classe permet de créer de nouveaux threads. Aujourd’hui, .NET propose des classes beaucoup plus simples à utiliser, mais Thread permet de définir finement certaines options comme la priorité, le lancement en arrière-plan…

static void Main(string[] args)
{
    Thread t = new Thread(new ThreadStart(MaLongueMethode));
    t.Start();

    for(int i=0; i<100000;i++)
    {
        Console.WriteLine("Exécution principale : {0}", i);
    }
    Console.ReadKey();
}

public static void MaLongueMethode()
{

    for(int i = 0; i<100000;i++)
    {
        Console.WriteLine("Exécution thread : {0}", i);
    }
}
Multithreading en c# - Résultat de l'exécution #1

A l’exécution on voit bien que les deux threads (celui qu’on a créé et le principal) s’exécute en parallèle.

La classe Thread offre de nombreuses possibilités. Pour en savoir plus allez faire un tour sur la documentation officielle.

Thread Pool

La création de Thread peut être gourmande en ressources. C’est pourquoi .NET propose des Threads « prêt-à-l’emploi ». Il suffit juste d’ajouter le traitement désiré dans le pool et il s’exécute dans un thread déjà disponible. Le nombre de Thread dans le pool n’est pas illimité. GetMaxThreads permet de savoir le nombre de threads pouvant être actifs simultanément. Si on dépasse cette limite, ils seront mis en file d’attente. Cette valeur maximum est modifiable avec la méthode SetMaxThreads.

static void Main(string[] args)
{
    ThreadPool.QueueUserWorkItem((s) => MaLongueMethode1());
    ThreadPool.QueueUserWorkItem((s) => MaLongueMethode2());

    Console.ReadKey();
}

public static void MaLongueMethode1()
{
    for(int i=0;i<100000;i++)
    {
        Console.WriteLine("Exécution thread 1 : {0}", i);
    }
}

public static void MaLongueMethode2()
{
    for (int i=0; i<100000;i++)
    {
        Console.WriteLine("Exécution thread 2 : {0}", i);
    }
}
Multithreading en c# - Résultat de l'exécution #2

Task

C# 4.0 a introduit la classe Task. L’avantage de cette classe c’est qu’on a un contrôle total sur la tache en cours, on peut récupérer une valeur de retour, suivre son avancement, l’annuler.

static void Main(string[] args)
{
    Task t = new Task(() => MaLongueMethode());
    t.Start();

    for(int i=0; i<100000;i++)
    {
        Console.WriteLine("Exécution thread principale : {0}", i);
    }
}

public static void MaLongueMethode()
{
    for(int i=0;i<100000;i++)
    {
        Console.WriteLine("Exécution thread 1 : {0}", i);
    }
}
Multithreading en c# - Résultat de l'exécution #3

L’exemple ci-dessus crée un nouveau Task et le lance

Pour récupérer une valeur retour avec un Task, on utilise Task<T> où T est le type retourné.

static void Main(string[] args)
{
    Task<int> t = new Task<int>(() => MaFonctionDeLaMort());
    t.Start();

    Console.WriteLine(t.Result); // affiche 42
    Console.ReadKey();
}

public static int MaFonctionDeLaMort()
{
    for (int i=0;i<100000;i++)
    {
        Thread.Sleep(0);
    }
    return 42;
}

Une autre fonctionnalité puissante des Task est Continuation. Il est possible de créer un Task qui ne s’exécutera que quand un autre aura fini son exécution.

static void Main(string[] args)
{
    Task t1 = new Task(() => Methode1());
    Task t2 = t1.ContinueWith(t => Methode2());

    t1.Start();

    Console.ReadKey();
}

public static void Methode1()
{
    for (int i=0;i<5;i++)
    {
      Console.WriteLine("Moi d'abord {0} ", i);
    }
}

public static void Methode2()
{
    for (int i=0; i<5;i++)
    {
        Console.WriteLine("Moi ensuite {0} ", i);
    }
}
Multithreading en c# - Résultat de l'exécution #5

La classe Task propose également les méthodes Wait , WaitAll , WhenAll, WhenAny qui gèrent la fin de l’exécution d’un ou plusieurs Task.

Cette partie vous a présenté la classe Thread et la classe Task. Dans une deuxième partie, je vous présenterai la classe Parallel et les mots clé async/await qui complèteront cet aperçu du multithreading en c#.

Auteur : Daniel MINKO FASSINOU

    3 commentaires

  1. Eric 19 octobre 2023 at 11 h 18 min Répondre

    Bonjour et grand merci
    il y a une petite faute de frappe dans le dernier exemple, ligne 13
    il faudrait « i5 »

    J’ai essayé tous ces exemples, super, c’est ce que je cherchais, il me manque juste un truc, comment passer des paramètres dans l’autre sens, du Main vers le Thread et également (existe-t-il plus propre que de faire la même chose en lui passant un paramètre) comment demander au Thread de se terminer.

    Bonne journée

    • Eric 19 octobre 2023 at 11 h 19 min Répondre

      arf, j’ai mis des < et >
      donc remplacer ligne 13 « i>5 » par « i<5 »

  2. Daniel MINKO FASSINOU 22 octobre 2023 at 11 h 59 min Répondre

    Bonjour Eric, effectivement. c’est corrigé. Merci

Laisser un commentaire




Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.