Concurrence et multithreading en C# : niveau avancé

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# : niveau avancé

\n\n

Dans le développement moderne en C# (.NET), la capacité à gérer efficacement la concurrence et le multithreading distingue un ingénieur expérimenté d'un débutant. Les connaissances de base sur Thread et les verrous simples ne suffisent plus pour créer des applications hautes performances, réactives et évolutives. Dans cet article, nous analyserons les techniques avancées : de la compréhension approfondie de async/await à l'utilisation de System.Threading.Channels et TPL Dataflow. Le contenu est destiné aux développeurs déjà familiers avec les bases du multithreading.

\n\n

1. Plongée approfondie dans async/await et SynchronizationContext

\n\n

De nombreux développeurs utilisent async/await sans comprendre pleinement comment le planificateur de tâches (Task Scheduler) et SynchronizationContext gèrent les continuations. À un niveau avancé, il est important de contrôler dans quel thread le code s'exécute après await.

\n\n

Par défaut, await capture le SynchronizationContext (ou TaskScheduler) actuel. Dans les applications d'interface utilisateur (WPF, WinForms), cela ramène l'exécution au thread principal. Dans ASP.NET Core et les applications console, le contexte est souvent absent et la continuation peut s'exécuter dans n'importe quel thread du pool.

\n\n

Pour un réglage fin, utilisez ConfigureAwait(false). Cela indique à l'environnement d'exécution de ne pas essayer de revenir au contexte d'origine, ce qui améliore les performances et prévient les blocages mutuels (deadlocks) dans le code de bibliothèque.

\n\n
public async Task<string> FetchDataAsync(HttpClient client)\n{\n    // La continuation ne capturera pas le contexte\n    var result = await client.GetStringAsync("https://api.example.com")\n                              .ConfigureAwait(false);\n    // Ce code s'exécutera dans n'importe quel thread du pool\n    return ProcessResult(result);\n}\n\npublic async Task<string> FetchDataWithContextAsync(HttpClient client)\n{\n    // La continuation reviendra au contexte d'origine (par exemple, le thread UI)\n    var result = await client.GetStringAsync("https://api.example.com");\n    // Ce code s'exécutera garantie dans le contexte d'origine\n    return ProcessResult(result);\n}
\n\n

Conseil avancé : Créez vos propres SynchronizationContext pour des scénarios non standard, par exemple, pour organiser une file d'attente de tâches avec un nombre fixe de threads.

\n\n

2. Task Parallel Library (TPL) et parallélisme de données

\n\n

TPL fournit des abstractions de haut niveau pour le parallélisme. Parallel.For et Parallel.ForEach divisent automatiquement les collections en morceaux (chunks) et les répartissent entre les threads. Cependant, à un niveau avancé, il est nécessaire de comprendre comment configurer le degré de parallélisme et la gestion des exceptions.

\n\n

Utilisez ParallelOptions pour limiter le nombre de threads, ainsi que ParallelLoopState pour une sortie anticipée de la boucle.

\n\n
var options = new ParallelOptions\n{\n    MaxDegreeOfParallelism = Environment.ProcessorCount / 2 // Utiliser la moitié des cœurs\n};\n\nParallel.ForEach(sourceData, options, (item, state) =>\n{\n    try\n    {\n        // Opération lourde\n        ProcessItem(item);\n    }\n    catch (Exception ex)\n    {\n        // Journaliser et interrompre l'exécution\n        Console.WriteLine($"Erreur : {ex.Message}");\n        state.Stop(); // Interrompt l'exécution de la boucle\n    }\n});
\n\n

Important : Parallel.ForEach ne garantit pas l'ordre de traitement. Si l'ordre est important, utilisez Parallel.ForEach avec un index ou PLINQ (AsParallel().AsOrdered()).

\n\n

3. Canaux (System.Threading.Channels) pour Producer-Consumer

\n\n

La classe Channel<T> est apparue dans .NET Core 3.0 et est devenue un outil puissant pour les scénarios producteur-consommateur. Elle est thread-safe, asynchrone et efficace. Les canaux existent

Blogs

Book Recommendations