În multe arhitecturi de backend, anumite componente generează date într-un ritm mult mai rapid decât pot fi acestea procesate și salvate pe disc sau transmise pe rețea. Folosirea unor colecții tradiționale precum BlockingCollection<T> sau cozi cu lock blochează firele de execuție și degradează masiv performanța.
Namespace-ul System.Threading.Channels oferă o implementare modernă, complet asincronă și de ultra-înaltă performanță a cozilor concurente producător-consumator, inspirată din canalele native din limbajul Go.
Implementarea unui Canal Delimitat (Bounded Channel) cu Backpressure
using System.Threading.Channels;
public class ServiciuProcesareEvenimente
{
// Creăm un canal delimitat cu capacitate de 100 de elemente:
private readonly Channel<string> _canal = Channel.CreateBounded<string>(new BoundedChannelOptions(100)
{
// Când coada este plină, producătorul așteaptă asincron fără să consume CPU (Backpressure):
FullMode = BoundedChannelFullMode.Wait,
SingleReader = true, // Optimizare internă fără lock dacă există un singur consumator
SingleWriter = false // Mai mulți producători concurenți
});
// 1. Producătorul publică mesaje:
public async ValueTask PublicaEvenimentAsync(string mesaj)
{
await _canal.Writer.WriteAsync(mesaj);
}
// 2. Consumatorul procesează fluxul asincron continuu:
public async Task PornesteConsumatorAsync(CancellationToken ct)
{
// ReadAllAsync returnează un IAsyncEnumerable ce se consumă elegant cu await foreach:
await foreach (string mesaj in _canal.Reader.ReadAllAsync(ct))
{
await ProceseazaMesajAsync(mesaj);
}
}
private async Task ProceseazaMesajAsync(string m)
{
await Task.Delay(10); // Simulăm persistența sau apelul extern
Console.WriteLine($"Mesaj procesat din canal: {m}");
}
}
Politici de Comportament la Saturarea Canalului (FullMode)
Wait(Recomandat): Producătorul este suspendat asincron până când consumatorul eliberează un slot în coadă.DropOldest: Elimină cel mai vechi mesaj din canal pentru a face loc noului mesaj (ideal pentru metrici în timp real).DropWrite: Renunță silențios la mesajul nou dacă coada este plină.