Introdução aos Worker Services no .NET

Um Worker Service no .NET é uma aplicação que roda em segundo plano, projetada para executar tarefas contínuas ou agendadas, sem a necessidade de interação direta com o usuário. Isso torna o Worker Service uma excelente opção para tarefas como processamento de dados, envio de e-mails, ou integração com filas de mensagens, especialmente em projetos que já possuem uma API existente.

Uma das grandes vantagens é que você pode implementar um Worker Service dentro de um projeto de API já existente, sem a necessidade de criar um novo projeto separado. Isso facilita o gerenciamento e a manutenção do código, além de permitir a reutilização de serviços e configurações da API.

Implementando um Worker Service em um projeto de API existente

O Worker Service pode ser implementado dentro da estrutura do projeto existente, por exemplo, em uma nova pasta chamada “Workers”. Essa abordagem centraliza o código e simplifica a manutenção.

Após criar uma pasta no local desejado, crie a classe. Para o nosso exemplo, eu criei uma classe chamada  “ProcesamentoPedidosWorker.cs” dentro dessa pasta, simulando um serviço que realiza o processamento de pedidos de um e-commerce:

				
					public class ProcesamentoPedidosWorker : BackgroundService
{
    private readonly ILogger<ProcesamentoPedidosWorker> _logger;

    public ProcesamentoPedidosWorker(ILogger<ProcesamentoPedidosWorker> logger)
    {
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Processando pedidos”);

            await Task.Delay(5000, stoppingToken);
        }
    }
}

				
			

Em nosso exemplo acima, a classe “ProcesamentoPedidosWorker”, herda da classe “BackgroundService”, uma abstração fornecida pelo .NET para facilitar a criação de serviços de segundo plano. No construtor de “ProcesamentoPedidosWorker”, o serviço de log (ILogger) é injetado para registrar informações, erros ou outras mensagens durante a execução do Worker. A injeção de dependência permite que o Worker use os serviços registrados no container da aplicação (como repositórios, serviços de e-mail, etc.). Neste caso, estamos injetando um logger para registrar logs da execução.

O método mais importante em um Worker Service é o “ExecuteAsync”, que contém a lógica principal que será executada em segundo plano. Nele criamos um loop “while” que  garante que o Worker continue executando enquanto o serviço não for cancelado. O “stoppingToken” é um token de cancelamento que sinaliza quando o serviço deve parar (como ao desligar a aplicação). 

Após isso, usamos o “ILogger” para registrar uma mensagem a cada execução. Por fim, o  método “Task.Delay(5000)” cria uma pausa de 5 segundos entre cada ciclo de execução, simulando a execução de uma tarefa periódica. O “stoppingToken” é passado para permitir que a tarefa seja interrompida caso o Worker seja cancelado.

Registre o Worker no Program.cs

Para que o Worker Service seja executado em conjunto com a sua API, você precisa registrá-lo no “Program.cs”.

No arquivo “Program.cs”, adicione o registro do serviço:

				
					builder.Services.AddHostedService<ProcesamentoPedidosWorker>();
				
			

No exemplo acima, utilizamos o método “AddHostedService” para registrar o Worker Service na coleção de serviços da aplicação. A classe “ProcesamentoPedidosWorker” é passada como o tipo do serviço, indicando ao .NET que essa classe será executada em segundo plano enquanto a API estiver ativa. Isso permite que o “ProcesamentoPedidosWorker” execute suas tarefas paralelamente, sem bloquear as operações da API, facilitando a implementação de processos contínuos ou agendados no seu projeto.

Injeção de Dependências no Worker Service

Assim como acontece nas APIs, o Worker Service pode aproveitar o ServiceProvider para a injeção de dependências. Isso permite o uso de serviços e repositórios que já existem no seu projeto, facilitando a integração.

No exemplo abaixo, vamos supor que você tenha um serviço “IEmailService” que envia e-mails, e deseja utilizá-lo no Worker:

				
					
public interface IEmailService
{
    Task SendEmailAsync(string to, string subject, string body);
}

public class EmailService : IEmailService
{
    public Task SendEmailAsync(string to, string subject, string body)
    {
        Console.WriteLine($"Enviando e-mail para {to}");
        //Implementação do envio de e-mail.
        return Task.CompletedTask;
    }
}

				
			

Agora, no seu Worker, você pode injetar esse serviço e utilizá-lo para enviar e-mails:

				
					public class ProcesamentoPedidosWorker: BackgroundService
{
    private readonly ILogger<ProcesamentoPedidosWorker> _logger;
    private readonly IEmailService _emailService;

    public ProcesamentoPedidosWorker(ILogger<ProcesamentoPedidosWorker> logger, IEmailService emailService)
    {
        _logger = logger;
        _emailService = emailService;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Processando pedidos”);
       await _emailService.SendEmailAsync("cliente@exemplo.com", "Pedido aprovado", "Seu pedido foi aprovado!");
            await Task.Delay(5000, stoppingToken);
        }
    }
}

				
			

E não se esqueça de registrar o serviço “IEmailService” no “Program.cs”:

				
					builder.Services.AddSingleton<IEmailService, EmailService>();
				
			

Dessa forma, o serviço de e-mail será usado pelo Worker sempre que ele for executado.

Acelere a sua carreira conosco!

Se você é Desenvolvedor .NET Júnior e quer acelerar sua carreira até nível Pleno com salário de R$7k+, ou mesmo busca a primeira vaga, conheça a Mentoria .NET StartClique aqui
Se é Desenvolvedor .NET Pleno ou Sênior e quer virar referência técnica em sua equipe e mercado, com salário de R$10k+, conheça a Mentoria .NET ExpertClique aqui

Conclusão

A integração de um Worker Service em um projeto de API existente no .NET oferece uma solução eficiente e centralizada para tarefas em segundo plano. O Worker Service pode ser facilmente adicionado em uma pasta do projeto, aproveitando toda a infraestrutura existente, como injeção de dependências e configurações. Além disso, ele é ideal para cenários como tarefas agendadas, monitoramento de serviços e processamento de dados.

Esse recurso permite criar uma arquitetura mais robusta, escalável e modular, facilitando o gerenciamento de processos de segundo plano na aplicação e proporcionando uma implementação eficiente e organizada para atender as necessidades específicas do sistema.