Async e Await: A ficha finalmente caiu!
- #.NET
- #.NET C#
Estudando o módulo "Trabalhando com Entity Framework com C#", fui em busca de entender melhor cada linha e método ensinados pelo Leonardo Buta. E minha mente deu um "estalo" para algo que já tinha utilizado em um projeto pessoal, mas nunca procurei saber exatamente o motivo de utilizar as instruções async e await. Exemplificando:
O código que utilizadei no módulo foi:
[HttpGet("GetByName/{nome}")]
public IActionResult GetByName(string nome)
{
var contatos = _context.Contatos.Where(c => c.Nome.Contains(nome)).ToList();
return Ok(contatos);
}
E me questionei o motivo de ser assim. Então, em uma rápida pesquisa, entendi que esse código era síncrono (bloqueia a thread enquanto vai ao banco) e que em projetos reais de APIs, costumam utilizar uma versão assíncrona para aguentar mais acessos simultâneos.
Pesando nisso, resolvi fazer a versão assíncrona, apenas para exemplificar:
[HttpGet("GetByName/{nome}")]
public async Task<IActionResult> GetByName(string nome)
{
// O 'await' libera a thread enquanto o banco trabalha
var contatos = await _context.Contatos
.Where(c => c.Nome.Contains(nome))
.ToListAsync();
return Ok(contatos);
}
O que mudou?
- async na assinatura: Indica ao compilador que este método pode ter pausas (awaits) e que ele deve ser quebrado numa "máquina de estados".
- Task<IActionResult>: O retorno não é mais o resultado imediato, mas uma "promessa" (Task) de que um IActionResult será entregue no futuro.
- ToListAsync(): Substituímos o .ToList() (que trava a execução) pelo .ToListAsync(). Este método envia o comando SQL para o banco, mas não fica esperando a resposta de braços cruzados.
- await: Esta é a mágica. Quando o código chega no await, o .NET libera a thread (o "operário") para voltar ao pool e atender outras requisições HTTP enquanto o banco de dados está processando a consulta.
Por que isso é importante?
Imagine um restaurante (sua API) com apenas um garçom (uma Thread).
- Síncrono (ToList): O garçom leva o pedido à cozinha e fica parado na porta, olhando para o cozinheiro, esperando o prato ficar pronto. Enquanto isso, novos clientes entram e ninguém os atende. O restaurante trava.
- Assíncrono (ToListAsync + await): O garçom entrega o pedido na cozinha e diz: "Quando estiver pronto, me avise". Ele volta imediatamente para o salão para atender outras mesas. O restaurante flui.
Então, o código assíncrono não faz a consulta ao banco ser mais rápida (pode até adicionar uns milissegundos de overhead), mas permite que seu servidor atenda milhares de requisições a mais simultaneamente sem travar por falta de threads.



