Concurrence et multithreading en C# : Guide complet pour les développeurs .NET

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

Concurrence et multithreading en C# : de Thread à async/await



Les applications modernes nécessitent de plus en plus souvent l'exécution simultanée de plusieurs tâches : du traitement des requêtes d'un serveur web aux calculs parallèles dans les programmes de bureau. En C# (.NET), il existe un arsenal puissant d'outils pour cela — des threads classiques (Thread) aux constructions de haut niveau async/await et à la bibliothèque Task Parallel Library (TPL). Dans cet article, nous allons examiner les concepts clés de la concurrence et du multithreading, leur application pratique et les meilleures pratiques.



Qu'est-ce que la concurrence et le multithreading ?



Avant de passer au code, il est important de comprendre la différence entre ces concepts :



  • Concurrence (Concurrency) — la capacité d'un programme à exécuter plusieurs tâches en basculant entre elles, créant l'illusion d'une exécution simultanée. Cela peut être réalisé même sur un seul cœur de processeur.
  • Multithreading (Multithreading) — une forme de concurrence où plusieurs threads (threads) s'exécutent physiquement en même temps sur un processeur multicœur.
  • Parallélisme (Parallelism) — un sous-ensemble du multithreading où différentes parties d'une tâche s'exécutent strictement simultanément sur différents cœurs.


En C#, vous pouvez utiliser à la fois des threads de bas niveau et des abstractions qui gèrent automatiquement les threads. Le choix dépend de la tâche : pour les opérations I/O-bound (travail avec des fichiers, réseau), async/await est plus adapté, et pour les CPU-bound (calculs) — Parallel.For ou Task.



Création et gestion des threads : la classe Thread



La classe System.Threading.Thread est le moyen le plus bas niveau de travailler avec les threads en C#. Elle offre un contrôle total, mais nécessite une synchronisation minutieuse.



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 enfant Console.WriteLine("Travail terminé."); }

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


Problèmes de la gestion manuelle des threads :

  • Complexité de la synchronisation (conditions de course, deadlocks).
  • Frais généraux élevés pour la création et la destruction des threads.
  • Absence de prise en charge intégrée du retour de résultat.


C'est pourquoi, dans le C# moderne, on préfère utiliser la Task Parallel Library.



Task Parallel Library (TPL) et async/await



La classe Task de l'espace de noms System.Threading.Tasks représente une opération asynchrone. Combinée aux mots-clés async et await, elle permet d'écrire du code asynchrone qui ressemble à du code synchrone.



Exemple de base avec Task



using System;using System.Threading.Tasks;

class Program{ static async Task Main() { Console.WriteLine("Début du travail.");

// Lance une tâche asynchrone Task<int> task = CalculateAsync(10);

// Pendant que la tâche s'exécute, on peut faire autre chose Console.WriteLine("Faire un autre travail...");

// Attend le résultat int result = await task; Console.WriteLine($"Résultat : {result}"); }

static async Task<int> CalculateAsync(int number) { await Task.Delay(1000); // Simulation d'une opération longue return number * number; }}

Blogs

Book Recommendations