Concorrência e Multithreading em C#: Nível Avançado

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Concorrência e Multithreading em C#: Nível Avançado



No desenvolvimento moderno em C#, concorrência e multithreading não são apenas extensões de capacidades, mas ferramentas fundamentais para criar aplicações rápidas, responsivas e escaláveis. No nível avançado, vamos além do simples uso de Task.Run e nos deparamos com as nuances dos agendadores, sincronização de contextos e padrões para trabalhar com dados compartilhados. Neste artigo, abordaremos os principais conceitos avançados de concorrência em C# (.NET) que o ajudarão a escrever código eficiente e seguro.



1. Task e ValueTask: Uso Aprofundado



A classe Task é a base da programação assíncrona em C#. No entanto, no nível avançado, é importante entender a diferença entre Task e ValueTask, bem como gerenciar o ciclo de vida das tarefas.



Quando usar ValueTask?

ValueTask é uma estrutura que evita a alocação de memória para um objeto Task quando o resultado já está disponível de forma síncrona. Isso é crítico para cenários de alto desempenho, como em métodos de cache.



public class CacheService{    private readonly Dictionary<string, string> _cache = new();

public async ValueTask<string> GetDataAsync(string key) { if (_cache.TryGetValue(key, out string value)) { // Resultado já existe, não cria Task return value; }

// Obtenção assíncrona de dados string data = await FetchFromDatabaseAsync(key); _cache[key] = data; return data; }

private async Task<string> FetchFromDatabaseAsync(string key) { await Task.Delay(100); // Simulação de atraso return $"Data for {key}"; }}


Tratamento Avançado de Erros e Cancelamento

Use CancellationToken para cancelar corretamente operações longas. Combine vários tokens através de CancellationTokenSource.CreateLinkedTokenSource.



public async Task ProcessWithTimeoutAsync(CancellationToken externalToken){    using var timeoutCts = new CancellationTokenSource(TimeSpan.FromSeconds(5));    using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(externalToken, timeoutCts.Token);

try { await LongRunningOperationAsync(linkedCts.Token); } catch (OperationCanceledException) { Console.WriteLine("Operação cancelada ou tempo limite excedido."); }}


2. SynchronizationContext e Agendadores de Tarefas



Compreender SynchronizationContext é necessário para trabalhar com threads de UI (WPF, WinForms) e ASP.NET Core. No nível avançado, você pode criar seus próprios contextos de sincronização.



Configuração de Contexto para Pool de Threads

Por padrão, await captura o SynchronizationContext atual. Para evitar isso (e prevenir deadlocks), use ConfigureAwait(false).



public async Task ProcessDataAsync(){    // Este código é executado no contexto original (ex.: UI)    await Task.Run(() => HeavyComputation()).ConfigureAwait(false);

// Após ConfigureAwait(false) — no contexto do pool de threads // Sem acesso a elementos da UI! Console.WriteLine("Executado na thread do pool");}


Criação de um Agendador Personalizado

Você pode implementar seu próprio TaskScheduler, por exemplo, para limitar o número de tarefas executadas simultaneamente (análogo ao SemaphoreSlim no nível do agendador).



public class LimitedConcurrencyTaskScheduler : TaskScheduler{    private readonly SemaphoreSlim _semaphore;    private int _runningTasks;

public LimitedConcurrencyTaskScheduler(int maxConcurrency) { _semaphore = new SemaphoreSlim(maxConcurrency);

Blogs

Book Recommendations