DEV Community

Cover image for Utilizando Worker Services no .NET Moderno
Danilo O. Pinheiro, dopme.io
Danilo O. Pinheiro, dopme.io

Posted on

Utilizando Worker Services no .NET Moderno

Com a evolução do .NET moderno (a partir do .NET Core 3.1 e especialmente no .NET 6+), os Worker Services se tornaram uma forma poderosa e nativa de criar serviços de longa execução, tarefas agendadas, processamento assíncrono e integrações com filas, brokers e jobs — tudo com a performance e a robustez do .NET.

Este artigo cobre:

  • 🔍 O que é um Worker Service
  • 🧱 Estrutura básica
  • 🛠️ Exemplos práticos (fila, cron, background tasks)
  • 🧭 Padrões arquiteturais recomendados
  • ✅ Boas práticas

🔍 O que é um Worker Service?

Um Worker Service é uma aplicação .NET baseada em IHostedService, executada em background, ideal para:

  • Processamento assíncrono (filas, brokers, eventos)
  • Envio de e-mails e notificações
  • Tarefas agendadas (cron jobs)
  • Monitoração e scraping
  • Orquestração de jobs
  • Serviços para rodar no Windows/Linux (como daemons)

Ele pode ser implantado em ambientes on-premise, Docker, Kubernetes, Azure App Services, Azure Container Instances, AWS Fargate, entre outros.


🧱 Estrutura de um Worker Service com .NET

Você pode criar um Worker com:

dotnet new worker -n MeuWorkerApp
Enter fullscreen mode Exit fullscreen mode

A estrutura base terá:

MeuWorkerApp/
├── Program.cs
├── Worker.cs
├── appsettings.json
Enter fullscreen mode Exit fullscreen mode

🧪 Exemplo simples

// Worker.cs
public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;

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

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Executando Worker em: {time}", DateTimeOffset.Now);
            await Task.Delay(10000, stoppingToken);
        }
    }
}
Enter fullscreen mode Exit fullscreen mode
// Program.cs (a partir do .NET 6)
using MeuWorkerApp;

var host = Host.CreateDefaultBuilder(args)
    .ConfigureServices(services =>
    {
        services.AddHostedService<Worker>();
    })
    .Build();

await host.RunAsync();
Enter fullscreen mode Exit fullscreen mode

🛠️ Exemplos práticos

📦 1. Consumindo uma fila (ex: RabbitMQ)

public class QueueWorker : BackgroundService
{
    private readonly IRabbitService _rabbit;

    public QueueWorker(IRabbitService rabbit)
    {
        _rabbit = rabbit;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _rabbit.Consume("fila-pagamentos", async (msg) =>
        {
            // Processa a mensagem
            await ProcessarPagamento(msg);
        });
    }
}
Enter fullscreen mode Exit fullscreen mode

⏰ 2. Job agendado com cron (ex: Hangfire, Quartz)

public class AgendadorWorker : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            if (DateTime.Now.Minute == 0) // Executa de hora em hora
            {
                await ExecutarJob();
            }

            await Task.Delay(60000, stoppingToken); // Espera 1 minuto
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Para algo mais robusto, use Quartz.NET ou Hangfire para agendamentos reais.


📤 3. Envio de notificações

public class NotificacaoWorker : BackgroundService
{
    private readonly INotificacaoService _service;

    public NotificacaoWorker(INotificacaoService service)
    {
        _service = service;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            await _service.EnviarPendentesAsync();
            await Task.Delay(TimeSpan.FromMinutes(5), stoppingToken);
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

🧭 Arquitetura Recomendada

Em aplicações modernas, recomenda-se separar os workers por responsabilidade:

src/
├── Workers/
│   ├── NotificacaoWorker.cs
│   ├── FilaWorker.cs
│   └── AgendadorWorker.cs
├── Application/        # Casos de uso
├── Domain/             # Regras de negócio
├── Infrastructure/     # Brokers, filas, logs, email
└── Shared/             # Utilitários comuns
Enter fullscreen mode Exit fullscreen mode

Workers devem delegar a lógica para serviços de domínio ou da aplicação (não misturar responsabilidade dentro do worker).


✅ Boas práticas

  • Mantenha os Workers leves — apenas orquestrando chamadas de serviços.
  • Use injeção de dependência (IServiceScopeFactory) para criar escopos.
  • Capture exceções e registre logs com contexto.
  • Prefira usar bibliotecas como Polly para tolerância a falhas (retries, circuit breaker).
  • Faça shutdowns respeitando o CancellationToken.

⚙️ Worker com escopo por operação

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
    while (!stoppingToken.IsCancellationRequested)
    {
        using var scope = _scopeFactory.CreateScope();
        var meuServico = scope.ServiceProvider.GetRequiredService<IMeuServico>();

        await meuServico.ProcessarAsync();

        await Task.Delay(5000, stoppingToken);
    }
}
Enter fullscreen mode Exit fullscreen mode

🚢 Publicação e Deploy

Você pode rodar Workers:

  • Como serviço Windows: sc create, New-Service
  • Em Linux (Systemd): criar unit .service
  • Em Docker:
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
COPY ./publish .
ENTRYPOINT ["dotnet", "MeuWorkerApp.dll"]
Enter fullscreen mode Exit fullscreen mode

📦 Quando usar um Worker em vez de uma API?

Situação Use API? Use Worker?
Exposição HTTP/REST
Escuta contínua de fila
Job de execução em horário fixo
Processamento assíncrono em background
Interface para usuário final

🔚 Conclusão

Worker Services são componentes essenciais nas aplicações modernas .NET. Eles permitem construir soluções desacopladas, assíncronas, escaláveis e resilientes. Ao usá-los com bons princípios arquiteturais, você amplia o poder da sua aplicação sem comprometer manutenibilidade.


🤝 Conecte-se comigo

Top comments (0)