Programmation Multithread en C# : Threads, Tâches et Synchronisation

Motivations pour l'utiilsation des threads

L'exécution simultanée de threads permet une gestion efficace des opérations parallèles. Cependant, l'accès concurrent aux données partagées nécessite des mécanismes de synchronisation pour éviter des états incohérents.

Fondamentaux des threads

Un thread représente un flux d'instructions indépendant. Dans les applications C#, le point d'entrée Main() s'exécute dans un thread principal. Pour des opérations parallèles comme la vérification orthographique, le traitement de fond ou les téléchargements, l'utilisation de multiples threads devient essentielle.

Création de threads via délégués asynchrones

Les délégués permettent d'invoquer des méthodes de manière asynchrone en utilisant le pool de threads. Quatre approches gèrent leur terminaison :

  • Vérification périodique (Polling)
  • Utilisation de handles d'attetne
  • Rappels asynchrones
  • Expressions Lambda
using System;
using System.Threading;

public delegate int OperationLongueDelegate(int valeur, int delai);

class AsyncExample
{
    static int OperationLongue(int valeur, int delai)
    {
        Console.WriteLine("Début opération longue");
        Thread.Sleep(delai);
        Console.WriteLine("Opération terminée");
        return valeur + 1;
    }

    static void Main()
    {
        OperationLongueDelegate delegue = OperationLongue;
        
        delegue.BeginInvoke(5, 2000, 
            ar => {
                int resultat = delegue.EndInvoke(ar);
                Console.WriteLine($"Résultat : {resultat}");
            }, 
            null);
            
        for (int i = 0; i < 50; i++) {
            Console.Write(".");
            Thread.Sleep(100);
        }
    }
}

Implémentation avec la classe Thread

using System;
using System.Threading;

class ThreadExample
{
    static void Main()
    {
        new Thread(() => 
            Console.WriteLine($"Thread secondaire ID: {Thread.CurrentThread.ManagedThreadId}")
        ).Start();
        
        Console.WriteLine($"Thread principal ID: {Thread.CurrentThread.ManagedThreadId}");
    }
}

Utilisation du pool de threads

using System;
using System.Threading;

class ThreadPoolDemo
{
    static void Main()
    {
        ThreadPool.QueueUserWorkItem(etat => 
        {
            for (int i = 0; i < 3; i++) {
                Console.WriteLine($"Itération {i}, Thread: {Thread.CurrentThread.ManagedThreadId}");
                Thread.Sleep(100);
            }
        });
        
        Thread.Sleep(500);
    }
}

Tâches avec Task et TaskFactory

using System;
using System.Threading.Tasks;

class TaskDemo
{
    static void Main()
    {
        Task tache = Task.Run(() => 
            Console.WriteLine($"Tâche exécutée, Thread: {Thread.CurrentThread.ManagedThreadId}")
        );
        
        Task continuation = tache.ContinueWith(t => 
            Console.WriteLine($"Continuation après tâche {t.Id}")
        );
        
        Task.WaitAll(tache, continuation);
    }
}

Parallélisme avec Parallel

using System;
using System.Threading.Tasks;

class ParallelExample
{
    static void Main()
    {
        Parallel.For(0, 5, index => 
            Console.WriteLine($"Traitement parallèle {index}")
        );
        
        Parallel.Invoke(
            () => Console.WriteLine("Tâche A"),
            () => Console.WriteLine("Tâche B")
        );
    }
}

Étiquettes: C# multithreading ThreadPool TaskParallelLibrary AsyncDelegate

Publié le 8 juin à 18h40