Domine inglês técnico de programação em 2025, seja qual for seu nível. Inscrição gratuita

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

Rocketseat

4 min de leitura
CSharp
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!"); }
O await só pode ser usado em métodos marcados com async, 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:
  1. dotTrace: excelente para identificar operações assíncronas que bloqueiam threads.
  1. 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.

Aprenda programação do zero e DE GRAÇA

No Discover você vai descomplicar a programação, aprender a criar seu primeiro site com a mão na massa e iniciar sua transição de carreira.

COMECE A ESTUDAR AGORA