ASP .NET Core - Transformando código síncrono para assíncrono - I
Hoje veremos como transformar código síncrono para assíncrono na plataforma .NET. |
Converter um código síncrono existente para um código assíncrono não é uma tarefa difícil e pode até se tornar bastante tedioso depois de fazer isso algumas vezes.
Uma das práticas recomendadas na programação assíncrona é usar async/await em todo o código, ou seja, você não deve misturar código síncrono e assíncrono sem considerar cuidadosamente as consequências. Em geral é uma má ideia bloquear o código assíncrono chamando Task.Wait ou Task.Result.
A abordagem recomendada é começar a conversão nas camadas de nível inferior e seguir em direção aos níveis de mais alto, ou seja, comece introduzindo async nos métodos da camada que acessam um banco de dados ou que acessam as APIs. Em seguida, introduza a programação assíncrona em seus métodos de serviço, depois a lógica de negócios e, por fim, a camada do usuário.
Se o seu código não tiver camadas bem definidas, você ainda pode fazer a conversão de síncrono para assíncrono usando async/await. Vais ser um pouco mais difícil mas não é impossível. (Esse é mais um motivo para você desenvolver usando camadas.)
A primeira etapa é identificar a operação assíncrona de baixo nível a ser convertida. Qualquer operação baseada em E/S é candidata para assíncrono. Exemplos comuns são consultas e comandos de banco de dados, chamadas a Web APIs e acesso ao sistema de arquivos.
Se a biblioteca subjacente tiver uma API pronta para async, tudo que você precisa fazer é adicionar um sufixo Async (ou sufixo TaskAsync) no nome do método síncrono.
Por exemplo, uma chamada do Entity Framework para First pode ser substituída por uma chamada para FirstAsync. Em alguns casos, você pode querer usar um tipo alternativo. Por exemplo, HttpClient é um substituto mais assíncrono para WebClient e HttpWebRequest.
Conversão usando async/await
Para mostrar um exemplo prático de conversão de um código síncrono para assíncrono vamos assumir que temos um projeto ASP .NET Core Web API onde temos implementado um repositório ProdutoRepository para acessar informações de Produtos que vai ser consumido por um controlador ProdutosController.
Nossa aplicação utiliza o Entity Framework Core e define uma classe de contexto ApplicationDbContext.
Assim em nossa aplicação Web API temos o código da implementação do padrão repositório definidos da seguinte forma:
1- interface IProdutoRepository
public interface IProdutoRepository { IEnumerable<Produto> GetProdutos(); Produto GetProduto(int? id); Produto Create(Produto produto); Produto Update(Produto produto); Produto Remove(Produto produto); } |
2- ProdutoRepository
using API_Conversao.Context; using API_Conversao.Models; using System.Collections.Generic; using System.Linq; namespace API_Conversao.Repositories public Produto Create(Produto produto) public Produto GetProduto(int? id) public IEnumerable<Produto> GetProdutos() public Produto Remove(Produto produto) public Produto Update(Produto produto) |
Temos assim um repositório para realizar o CRUD básico usando o contexto (_produtoContext) do EF Core e foi implementado usando o código síncrono.
A seguir temos o código do controlador que usa este repositório :
using API_Conversao.Models; using API_Conversao.Repositories; using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; namespace API_Conversao.Controllers public ProdutosController(IProdutoRepository produtoService) // api/produtos [HttpGet("{id}", Name = "GetProduto")] if (produto == null) [HttpPost] _produtoRepository.Create(produto); return new CreatedAtRouteResult("GetProduto", [HttpPut("{id}")] _produtoRepository.Update(produto); return Ok(produto); [HttpDelete("{id}")] |
O controlador de
ProdutosController funciona perfeitamente em
conjunto com o EF Core; todos os métodos HTTP descritos se relacionam com
os respectivos métodos EF Core DbContext por meio
do repositório.
Os tipos ActionResult representam vários códigos de
status HTTP e permite retornar um tipo ou um código de status.
Os métodos do controlador pode ter os seguintes códigos de status HTTP :
Assim temos o controlador usando métodos Action todos com a programação síncrona.
Nosso objetivo será converter tanto o repositório como o controlador usando a programação assíncrona.
Seguindo as recomendações vamos iniciar a conversão pela camada de nível inferior que é representando pelo nosso Repositório.
Assim na próxima parte do artigo vamos iniciar a conversão do código usando async/await.
'Porque em esperança fomos salvos. Ora a esperança que
se vê não é esperança; porque o que alguém vê como o esperará ? Mas, se
esperamos o que não vemos, com paciência o esperamos.'
Romanos 8:24,25
Referências: