Você colocou async
no método, await
em tudo quanto é canto, a IDE parou de reclamar... mas o sistema continua lento. Dá até vontade de gritar: “Tô usando async! Por que isso ainda parece síncrono com insônia?”
Calma, dev. Bora entender onde tá o bug invisível (e como evitá-lo no mundo real do .NET).
Primeiro, um alerta: async/await
não é magia negra ⚠️
Sim, a sintaxe parece um encantamento de Hogwarts: await AbrirConexaoComBancoAsync();
Mas por trás disso, tem threads, tasks, contextos de sincronização, e um compilador trabalhando mais do que o estagiário em semana de entrega.
E é aí que mora o perigo: muita gente usa async/await
achando que está paralelizando tudo, quando na real está só empilhando promessas mal resolvidas.
Entendendo a armadilha: o falso assíncrono
Veja este exemplo clássico de cilada:
public async Task<List<Usuario>> GetUsuariosAsync()
{
var lista = new List<Usuario>();
foreach (var id in listaDeIds)
{
var usuario = await _servicoUsuarios.BuscarPorIdAsync(id);
lista.Add(usuario);
}
return lista;
}
Você olha isso e pensa:
“Olha que lindo, tudo assíncrono!”
Mas não. Tá tudo sequencial. Um await
só roda depois que o outro termina.
Isso é o equivalente a usar Uber pra ir pra padaria da esquina. Funciona? Funciona. Mas tá longe de ser eficiente.
A solução? Task.WhenAll
na sua vida 🧠
Se o serviço permite chamadas em paralelo, faça isso:
public async Task<List<Usuario>> GetUsuariosAsync()
{
var tarefas = listaDeIds
.Select(id => _servicoUsuarios.BuscarPorIdAsync(id));
var resultados = await Task.WhenAll(tarefas);
return resultados.ToList();
}
Agora sim: todas as requisições estão rolando ao mesmo tempo, aproveitando o que a programação assíncrona tem de melhor.
Outro vilão oculto: o tal do ConfigureAwait(false)
Se você tá desenvolvendo em ASP.NET Core, usar ou não usar ConfigureAwait(false)
pode ser a diferença entre uma app escalável ou uma panela de pressão explodindo.
Por padrão, await
tenta capturar o contexto de sincronização original (tipo, o contexto do thread do request).
Mas no ASP.NET Core, você não precisa disso. E evitar essa captura libera a thread mais cedo.
Exemplo:
await _algumaCoisa.FazAlgoAsync().ConfigureAwait(false);
Menos overhead. Mais performance. Mais paz.
Tá, mas quando NÃO usar paralelismo?
Nem todo async
precisa ser paralelo.
- Se os métodos compartilham estado (tipo, gravam na mesma lista), melhor evitar.
- Se sua fonte de dados limita chamadas concorrentes (como alguns bancos ou APIs), paralelismo pode prejudicar.
- Se o serviço for "assíncrono em aparência, mas síncrono por dentro", também não adianta muito...
Ou seja: assíncrono é ótimo — mas nem tudo que brilha é Task.Run()
.
Moral da thread
Async não resolve tudo, mas bem usado é poder puro ⚙️
O uso de async/await
no C# é uma das maiores evoluções da linguagem.Mas usá-los de forma ingênua é como dirigir uma Ferrari com freio de mão puxado: bonito por fora, frustrante por dentro.
Seja esperto. Entenda o que tá rodando por baixo.
Meça, monitore, e use as ferramentas com propósito.
Seu sistema, seu time e seu cliente vão agradecer (e talvez até o seu GC também).
P.S.:
Se você leu até aqui e pensou “puts, eu faço isso no meu código😬” — respira. Refatora.
E compartilha esse artigo com o time antes que mais alguém invente de colocar async void
no Controller.
Top comments (0)