Programação assíncrona em C#: task, await e concorrência

Rocketseat

Conheça o Rocketseat Para Empresas
Oferecemos soluções personalizadas para empresas de todos os portes.
Já imaginou escrever código que se parece com uma sequência simples de instruções, mas executa tarefas de forma eficiente e sem bloqueios? Bem-vindo ao mundo da programação assíncrona em C#! Hoje, vamos explorar como Task, await e técnicas de concorrência podem transformar a maneira como você desenvolve aplicações.
O que é programação assíncrona e por que ela é importante?
A programação assíncrona é uma abordagem que permite que um programa continue executando outras tarefas enquanto aguarda a conclusão de operações demoradas, como leitura de arquivos, chamadas de API ou consultas a banco de dados. Isso resolve gargalos de I/O e melhora a responsividade de aplicações desktop e web.
Imagine pedir um café em uma cafeteria movimentada. Você faz o pedido, senta-se e começa a responder e-mails enquanto espera ser chamado. Essa é uma analogia perfeita para o assíncronismo: tarefas sendo realizadas em paralelo, mas sem bloqueio.
Na programação síncrona, o código espera que cada etapa seja concluída antes de prosseguir, o que pode ser ineficiente. Com a programação assíncrona, você pode iniciar várias tarefas simultaneamente e gerenciá-las de forma eficaz.
Os pilares: task e await
Task: o que é e como utilizá-la
No C#, uma Task representa uma operação que pode estar em execução ou ser agendada para execução. Ela é a base da programação assíncrona no .NET. Você pode criar uma Task de várias formas, como:
Task tarefa = Task.Run(() => { Console.WriteLine("Executando tarefa..."); });
As Tasks têm estados bem definidos:
- Created: quando a tarefa foi criada, mas ainda não iniciada.
- Running: a tarefa está sendo executada.
- RanToCompletion: finalizou com sucesso.
- Faulted ou Canceled: ocorreu um erro ou foi cancelada.
Você também pode criar Tasks que retornam valores usando
Task<T>:Task<int> resultado = Task.Run(() => 42); Console.WriteLine($"Resultado: {resultado.Result}");
await: simplificando o assíncronismo
A palavra-chave await permite que você pause a execução de um método até que uma Task seja concluída, sem bloquear a thread chamadora. Por exemplo:
async Task ExemploAsync() { Console.WriteLine("Iniciando..."); await Task.Delay(2000); Console.WriteLine("Finalizado!"); }
Oawaitsó pode ser usado em métodos marcados comasync, sinalizando que eles podem conter operações assíncronas.
Concatenando e orquestrando tasks
Um dos maiores benefícios da programação assíncrona é a capacidade de executar múltiplas tarefas simultaneamente. O .NET fornece métodos como
Task.WhenAll e Task.WhenAny para orquestrar essas tarefas.Executando tarefas em paralelo com Task.WhenAll
Se você precisa esperar por várias operações, como downloads de arquivos, pode usar
Task.WhenAll:var tarefa1 = Task.Delay(3000); var tarefa2 = Task.Delay(2000); await Task.WhenAll(tarefa1, tarefa2); Console.WriteLine("Ambas as tarefas concluídas!");
Aguardando a primeira tarefa com Task.WhenAny
Caso precise agir assim que a primeira tarefa for concluída,
Task.WhenAny é a escolha certa:var tarefas = new[] { Task.Delay(3000), Task.Delay(2000) }; var primeiraConcluida = await Task.WhenAny(tarefas); Console.WriteLine("Uma tarefa foi concluída!");
Tratamento de exceções em código assíncrono
Erros em código assíncrono podem ser capturados com blocos
try-catch, garantindo que o aplicativo lide bem com falhas:try { await Task.Run(() => throw new InvalidOperationException("Erro!")); } catch (Exception ex) { Console.WriteLine($"Exceção capturada: {ex.Message}"); }
Quando você usa
Task.WhenAll, exceções múltiplas podem ocorrer. Nesse caso, elas são encapsuladas em um AggregateException, que precisa ser tratado cuidadosamente.Concorrência e paralelismo: qual é a diferença?
- Concorrência: várias tarefas em execução ao mesmo tempo, mas compartilhando os mesmos recursos.
- Paralelismo: tarefas sendo executadas simultaneamente em múltiplos threads ou núcleos.
No .NET, o Thread Pool gerencia as threads de forma eficiente, priorizando operações assíncronas baseadas em I/O para maximizar o desempenho.
Para operações CPU-bound, use
Task.Run. Já para operações I/O-bound, aproveite o modelo assíncrono com await.Lidando com recursos compartilhados
Problemas de concorrência, como race conditions (condições de corrida) e deadlocks (travamentos), podem surgir quando várias tarefas tentam acessar simultaneamente um recurso compartilhado. Para evitar esses problemas, você pode utilizar mecanismos de sincronização como o SemaphoreSlim, que permite gerenciar o acesso exclusivo a esses recursos:
SemaphoreSlim semaphore = new SemaphoreSlim(1); await semaphore.WaitAsync(); try { Console.WriteLine("Acesso exclusivo a um recurso."); } finally { semaphore.Release(); }
O
SemaphoreSlim cria uma fila ordenada de acesso, garantindo que apenas um determinado número de tarefas possa acessar o recurso ao mesmo tempo. No exemplo acima, limitamos o acesso a uma única tarefa. Isso resolve race conditions e evita conflitos ao manipular recursos compartilhados.Imagine o semaphore como um gerente de fila em uma cafeteria: ele permite que apenas uma pessoa de cada vez use a máquina de café, garantindo ordem e evitando conflitos. Implementar um controle como esse não só melhora a estabilidade do código, mas também evita problemas difíceis de diagnosticar, como resultados inconsistentes ou bloqueios inesperados.
Performance e boas práticas
Evite async void
Métodos
async void não retornam uma Task, dificultando o monitoramento de sua execução e o tratamento de erros. Prefira async Task ou async Task<T>, pois eles permitem usar await para rastrear quando uma operação termina e capturar exceções.// Correto: async Task ProcessarDadosAsync() { await Task.Delay(1000); Console.WriteLine("Dados processados!"); }
Use ConfigureAwait(false)
Para operações que não precisam atualizar o contexto de sincronização (como aplicações de biblioteca), usar
ConfigureAwait(false) melhora o desempenho e evita deadlocks em cenários específicos:await Task.Delay(2000).ConfigureAwait(false);
Essa abordagem é especialmente útil em bibliotecas ou serviços que realizam chamadas assíncronas, pois minimiza a sobrecarga do contexto.
Diagnóstico e monitoramento
A performance de código assíncrono pode ser monitorada com ferramentas como dotTrace ou o Visual Studio Diagnostic Tools. Elas ajudam a identificar gargalos em tarefas assíncronas, analisando o consumo de CPU, tempo de espera e travamentos:
- dotTrace: excelente para identificar operações assíncronas que bloqueiam threads.
- Visual Studio Diagnostic Tools: ideal para depuração em tempo real, mostrando o comportamento do código durante a execução.
Integrar essas ferramentas ao seu fluxo de trabalho garante aplicações mais robustas e de alta performance.
Próximos passos
Agora que você compreendeu os fundamentos e técnicas da programação assíncrona, é hora de transformar teoria em prática. Experimente criar métodos assíncronos, otimize seus projetos e resolva desafios reais do dia a dia. A prática é o segredo para dominar essa habilidade essencial no mercado.
Com mais de 100 horas de conteúdo direto ao ponto, você aprenderá desde os fundamentos do C# e .NET até o desenvolvimento de APIs robustas e bibliotecas organizadas. Tudo isso com o acompanhamento de especialistas como Welisson Arley, que traz experiência prática e insights valiosos para que você se destaque.
O que você vai conquistar ao fazer parte dessa formação?
- Projetos reais para construir um portfólio de brilhar os olhos.
- Certificado reconhecido pelo mercado, validando seu conhecimento.
- Suporte e acompanhamento personalizado para tirar todas as suas dúvidas.
- Networking com uma comunidade incrível de desenvolvedores.
Por que aprender C#?
- Versatilidade: crie aplicativos para web, mobile e até jogos.
- Alta demanda: grandes empresas como Uber, Spotify e Slack utilizam C#.
- Salários competitivos: com níveis que podem chegar a R$ 12 mil para profissionais seniores.
Garanta já a sua vaga e comece a dominar o C#! Não perca a oportunidade de transformar sua carreira com a Rocketseat. Explore mais clicando aqui.
Nos vemos na formação! Continue explorando, experimentando e, acima de tudo, codando.
Conheça o Rocketseat Para Empresas
Oferecemos soluções personalizadas para empresas de todos os portes.
Artigos_
Explore conteúdos relacionados
Descubra mais artigos que complementam seu aprendizado e expandem seu conhecimento.
NewsletterReceba conteúdos inéditos e novidades gratuitamente