Travailler avec les files d'attente de tâches en C# : 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 aux files d'attente de tâches en C#



Dans la programmation multithread moderne, la file d'attente de tâches (task queue) est un modèle fondamental pour organiser le traitement asynchrone des données. En C# (.NET), ce modèle est implémenté via plusieurs mécanismes puissants qui permettent aux développeurs de gérer efficacement les threads d'exécution et de répartir la charge de travail.



La file d'attente de tâches résout le problème classique du producteur-consommateur (producer-consumer), où une partie du code crée des tâches et une autre les traite. Dans cet article, nous examinerons les principales façons d'implémenter des files d'attente de tâches en C# : des collections simples aux canaux modernes (Channel).



Approches principales pour implémenter des files d'attente de tâches



1. ConcurrentQueue — file d'attente thread-safe



L'implémentation la plus simple et de bas niveau est ConcurrentQueue<T> de l'espace de noms System.Collections.Concurrent. Elle fournit les méthodes thread-safe Enqueue et TryDequeue.



using System;using System.Collections.Concurrent;using System.Threading.Tasks;

public class SimpleTaskQueue{ private readonly ConcurrentQueue<Action> _tasks = new(); private readonly Task _worker;

public SimpleTaskQueue() { _worker = Task.Run(ProcessTasks); }

public void Enqueue(Action task) { _tasks.Enqueue(task); }

private void ProcessTasks() { while (true) { if (_tasks.TryDequeue(out var task)) { task(); } } }}


Avantages :

  • Simplicité d'utilisation
  • Faible consommation mémoire
  • Thread-safe sans verrous


Inconvénients :

  • Attente active (busy waiting) dans la boucle
  • Absence de signalisation pour les nouvelles tâches
  • Difficulté d'arrêt


2. BlockingCollection — file d'attente avec blocage



BlockingCollection<T> résout le problème de l'attente active. Elle fournit les méthodes Add et Take, qui bloquent le thread jusqu'à ce que des données soient disponibles.



using System;using System.Collections.Concurrent;using System.Threading.Tasks;

public class BlockingTaskQueue : IDisposable{ private readonly BlockingCollection<Action> _tasks = new(new ConcurrentQueue<Action>()); private readonly Task[] _workers; private bool _disposed;

public BlockingTaskQueue(int workerCount = 4) { _workers = new Task[workerCount]; for (int i = 0; i < workerCount; i++) { _workers[i] = Task.Run(ProcessTasks); } }

public void Enqueue(Action task) { _tasks.Add(task); }

private void ProcessTasks() { foreach (var task in _tasks.GetConsumingEnumerable()) { if (_disposed) break; task(); } }

public void CompleteAdding() { _tasks.CompleteAdding(); }

public void Dispose() { _disposed = true; _tasks.CompleteAdding(); Task.WaitAll(_workers); _tasks.Dispose(); }}


Caractéristiques clés :

  • Blocage automatique du thread en l'absence de tâches
  • Prise en charge de l'annulation via CancellationToken
  • Possibilité de limiter la capacité de la file d'attente
  • Arrêt sécurisé via CompleteAdding


Approche moderne : Channel<T>



Depuis .NET Core 3.0 et .NET 5, C# a introduit System.Threading.Channels.Channel<T> — c'est l'implémentation la plus performante et la plus flexible de file d'attente de tâches. Elle prend en charge les opérations asynchrones, l'annulation et la limitation du débit.

Blogs

Book Recommendations