C# Academy · Aula

Trabalhos agendados com Quartz.NET

Defina trabalhos e gatilhos com Quartz.NET, use expressões cron e integre tudo ao DI do ASP.NET Core.

Aula 4 de 412 etapas

Trabalhos agendados com Quartz.NET é uma aula grátis de C# Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de C# Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de C# Academy inclui 4 aulas no total.

Por que Quartz.NET

Quando você precisa de expressões cron, persistência de trabalhos, agrupamento, políticas de repetição e cadeias de trabalhos — o Quartz.NET fornece um agendador pronto para produção, além do que o PeriodicTimer oferece. Ele é a versão .NET do popular agendador Quartz para Java.

Instalando o Quartz.NET

Adicione os pacotes Quartz e Quartz.AspNetCore. A integração com o ASP.NET registra automaticamente o agendador como um serviço hospedado.

# Install packages
dotnet add package Quartz
dotnet add package Quartz.AspNetCore

# Optional: persistence (requires Quartz.Serialization.Json too)
# dotnet add package Quartz.Jobs
# dotnet add package Quartz.Plugins

Definindo um trabalho

Implemente IJob (ou IAsyncJob nas versões mais recentes do Quartz) com um método Execute. O contexto do trabalho fornece dados de execução e informações sobre o gatilho atual.

using Quartz;

[DisallowConcurrentExecution] // prevent overlapping executions
public class ReportGeneratorJob : IJob
{
    private readonly IReportService _reports;
    private readonly ILogger<ReportGeneratorJob> _logger;

    public ReportGeneratorJob(IReportService r, ILogger<ReportGeneratorJob> l)
    { _reports = r; _logger = l; }

    public async Task Execute(IJobExecutionContext context)
    {
        _logger.LogInformation("Generating report at {Time}", DateTime.UtcNow);
        await _reports.GenerateDailyReportAsync(context.CancellationToken);
        _logger.LogInformation("Report generated");
    }
}

Registrando o Quartz no ASP.NET Core

Use AddQuartz para configurar o agendador e AddQuartzHostedService para executá-lo como um IHostedService. Os trabalhos e gatilhos são configurados na expressão lambda.

builder.Services.AddQuartz(q =>
{
    q.UseMicrosoftDependencyInjectionJobFactory();

    var jobKey = new JobKey("ReportGenerator");
    q.AddJob<ReportGeneratorJob>(opts => opts.WithIdentity(jobKey));

    q.AddTrigger(opts => opts
        .ForJob(jobKey)
        .WithIdentity("ReportTrigger")
        .WithCronSchedule("0 0 8 * * ?") // 8:00 AM daily
    );
});

builder.Services.AddQuartzHostedService(q =>
    q.WaitForJobsToComplete = true);

Sintaxe de expressões cron

O Quartz usa uma expressão cron com 6 ou 7 campos: seconds minutes hours day-of-month month day-of-week [year]. A expressão cron do Quartz é ligeiramente diferente da expressão cron do Unix — os segundos vêm primeiro.

// Quartz cron format: sec min hour dom month dow [year]

"0 0 8 * * ?"     // Every day at 8:00 AM
"0 0/30 9-17 * * ?" // Every 30 min, 9 AM - 5 PM weekdays
"0 0 0 1 * ?"     // First day of every month at midnight
"0 0 6 ? * MON-FRI" // Every weekday at 6 AM
"0 0/5 * * * ?"   // Every 5 minutes

// Tip: use cronmaker.com or crontab.guru to build expressions

Gatilhos simples

Para agendas baseadas em intervalos sem a complexidade do cron, use gatilhos simples com WithSimpleSchedule.

q.AddTrigger(opts => opts
    .ForJob(jobKey)
    .WithIdentity("CleanupTrigger")
    .StartNow()
    .WithSimpleSchedule(s => s
        .WithIntervalInHours(1)
        .RepeatForever())
);

// Or a one-shot trigger:
q.AddTrigger(opts => opts
    .ForJob(jobKey)
    .WithIdentity("OneShot")
    .StartAt(DateTimeOffset.UtcNow.AddMinutes(5)));

Mapa de dados do trabalho

Passe parâmetros de execução aos trabalhos por meio de JobDataMap. Acesse-os dentro de Execute usando context.JobDetail.JobDataMap.

q.AddJob<EmailJob>(opts => opts
    .WithIdentity("EmailJob")
    .UsingJobData("to", "admin@example.com")
    .UsingJobData("subject", "Daily Digest"));

// Inside the job:
public async Task Execute(IJobExecutionContext context)
{
    var to      = context.JobDetail.JobDataMap.GetString("to");
    var subject = context.JobDetail.JobDataMap.GetString("subject");
    await _mailer.SendAsync(to!, subject!, "body");
}

DisallowConcurrentExecution

[DisallowConcurrentExecution] impede que uma nova instância do trabalho seja iniciada enquanto a anterior ainda estiver em execução. Isso é essencial para trabalhos que acessam recursos compartilhados.

[DisallowConcurrentExecution]
public class InventorySyncJob : IJob
{
    // If a sync takes > 1 minute and triggers every minute,
    // the next trigger is delayed until this one completes

    public async Task Execute(IJobExecutionContext context)
    {
        await SyncInventoryAsync(context.CancellationToken);
    }
}

// Without [DisallowConcurrentExecution], multiple instances
// could run in parallel, causing data conflicts.

Tratamento de exceções e repetição

Envolva o código do trabalho em try/catch. Lance JobExecutionException para sinalizar ao Quartz que o trabalho deve ser disparado novamente imediatamente ou após um atraso.

public async Task Execute(IJobExecutionContext context)
{
    try
    {
        await ProcessAsync(context.CancellationToken);
    }
    catch (TransientException ex)
    {
        // Ask Quartz to retry immediately
        var jobException = new JobExecutionException(ex)
        {
            RefireImmediately = true
        };
        throw jobException;
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Job failed — not retrying");
        // Don't rethrow — job is done
    }
}

Exemplo real: agendador com vários trabalhos

Uma configuração do Quartz pronta para produção, com vários trabalhos em agendas diferentes, todos usando DI para os serviços.

builder.Services.AddQuartz(q =>
{
    q.UseMicrosoftDependencyInjectionJobFactory();

    // Daily report at 8 AM
    var reportKey = new JobKey("DailyReport");
    q.AddJob<ReportGeneratorJob>(o => o.WithIdentity(reportKey));
    q.AddTrigger(o => o.ForJob(reportKey)
        .WithCronSchedule("0 0 8 * * ?"));

    // Inventory sync every 15 minutes
    var syncKey = new JobKey("InventorySync");
    q.AddJob<InventorySyncJob>(o => o.WithIdentity(syncKey));
    q.AddTrigger(o => o.ForJob(syncKey)
        .WithSimpleSchedule(s => s
            .WithIntervalInMinutes(15)
            .RepeatForever()));

    // Cache cleanup every night at 2 AM
    var cacheKey = new JobKey("CacheCleanup");
    q.AddJob<CacheCleanupJob>(o => o.WithIdentity(cacheKey));
    q.AddTrigger(o => o.ForJob(cacheKey)
        .WithCronSchedule("0 0 2 * * ?"));
});

Verificação rápida

O que o atributo [DisallowConcurrentExecution] faz em um trabalho do Quartz.NET?

Recapitulação: trabalhos agendados com Quartz.NET

Principais conclusões:

  • Quartz.NET: agendador pronto para produção com cron, persistência e agrupamento
  • Defina trabalhos implementando IJob com um método Execute
  • Registre com AddQuartz + AddQuartzHostedService; os trabalhos são compatíveis com DI
  • Formato cron: segundos minutos horas dia do mês mês dia da semana — observe que os segundos vêm primeiro
  • [DisallowConcurrentExecution]: aguarde a conclusão da execução atual antes de disparar novamente
  • Use JobDataMap para passar parâmetros de execução aos trabalhos
Grátis para começar

Aprenda C# com um tutor de IA — grátis

Escreva e execute código real no seu navegador, obtenha ajuda instantânea de um tutor de IA 24/7 e continue de onde parou na web ou no app.

Cursos
93
Aulas
346

Perguntas Frequentes

A aula “Trabalhos agendados com Quartz.NET” é grátis?

Sim — o texto completo de “Trabalhos agendados com Quartz.NET” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de C# Academy, atualize para CoddyKit PRO. O curso de C# Academy inclui 4 aulas no total.

O que vou aprender em “Trabalhos agendados com Quartz.NET”?

Defina trabalhos e gatilhos com Quartz.NET, use expressões cron e integre tudo ao DI do ASP.NET Core. Você pratica C# Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar C# Academy?

Nenhuma experiência prévia é necessária. C# Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.

Quanto tempo leva a aula “Trabalhos agendados com Quartz.NET”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de C# Academy?

Sim. Cada aula de C# Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. IHostedService e BackgroundService
  2. Projetos de Worker Service
  3. Tarefas periódicas e temporizadores
  4. Trabalhos agendados com Quartz.NET
← Voltar para C# Academy