Concurrence et multithreading en C# : de A à Z — guide complet

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction : pourquoi la concurrence en C# ?

Les applications modernes nécessitent de plus en plus l'exécution simultanée de plusieurs opérations. L'utilisateur s'attend à ce que l'interface ne se "bloque" pas lors du chargement des données, et que le serveur puisse traiter des milliers de requêtes en parallèle. En C# (.NET), pour résoudre ces problèmes, on utilise la concurrence — la capacité d'un programme à exécuter plusieurs tâches dans des intervalles de temps qui se chevauchent — et le multithreading — l'implémentation de la concurrence à l'aide de plusieurs threads d'exécution.

Dans cet article, nous aborderons les concepts clés : des Thread de base aux async/await et Parallel modernes. Vous apprendrez à choisir le bon outil pour chaque tâche et à éviter les erreurs typiques telles que les blocages mutuels (deadlocks) et les conditions de course (race conditions).



1. Les bases : Thread et ThreadPool

Travailler avec les threads via Thread

La classe System.Threading.Thread est la manière la plus bas niveau de créer des threads. Chaque thread possède sa propre pile et s'exécute indépendamment. Exemple de création et de lancement d'un thread :

using System;using System.Threading;

class Program{ static void Main() { Thread thread = new Thread(DoWork); thread.Start(); // Le thread principal continue son travail for (int i = 0; i < 5; i++) { Console.WriteLine($"Thread principal : {i}"); Thread.Sleep(100); } thread.Join(); // Attend la fin du thread secondaire }

static void DoWork() { for (int i = 0; i < 5; i++) { Console.WriteLine($"Thread de travail : {i}"); Thread.Sleep(150); } }}

Important : La création d'un nouveau thread est une opération coûteuse. Pour la création fréquente de threads de courte durée, il est préférable d'utiliser ThreadPool.



ThreadPool — le pool de threads

ThreadPool gère un ensemble de threads de travail qui sont réutilisés. C'est plus efficace que de créer un Thread manuellement. Exemple :

ThreadPool.QueueUserWorkItem(state =>{    Console.WriteLine("La tâche s'exécute dans le pool de threads");    Thread.Sleep(500);    Console.WriteLine("Tâche terminée");});

Console.WriteLine("Le thread principal continue son travail");Console.ReadKey();

Limitation : Vous ne pouvez pas contrôler directement la priorité ou le nom d'un thread du pool. Pour un contrôle plus fin, utilisez Task.



2. Task et la Task Parallel Library (TPL)

Task — l'approche moderne

Depuis .NET 4.0, Task est devenu l'outil principal pour les opérations asynchrones. Il abstrait les threads et permet de travailler avec les résultats d'exécution. Exemple :

using System;using System.Threading.Tasks;

class Program{ static async Task Main() { Task<int> task = Task.Run(() => ComputeResult(10)); // On peut faire d'autre travail Console.WriteLine("En attente du résultat..."); int result = await task; Console.WriteLine($"Résultat : {result}"); }

static int ComputeResult(int value) { Task.Delay(1000).Wait(); // Simulation d'une opération longue return value * 2; }}

Avantages clés :

  • Retourne un résultat via Task<T>
  • Prend en charge l'annulation via CancellationToken
  • Permet de combiner des tâches (ContinueWith, WhenAll, WhenAny)
  • Intégré avec async/await


Parallel — pour les boucles parallèles

La classe Parallel simplifie l'exécution de boucles avec parallélisation. Exemple :

using System;using System.Threading.Tasks;

class Program{ static void Main()\

Blogs

Book Recommendations