C# Academy · レッスン

Quartz.NETのスケジュールジョブ

Quartz.NETでジョブとトリガーを定義し、cron式を使って、ASP.NET CoreのDIと統合します。

レッスン 4/412 ステップ

「Quartz.NETのスケジュールジョブ」はCoddyKit上の無料C# Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC# Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C# Academyコースには全4レッスンが含まれています。

Quartz.NETを使う理由

cron式、ジョブの永続化、クラスタリング、再試行ポリシー、ジョブチェーンが必要な場合、Quartz.NETはPeriodicTimerを超える本番環境向けのスケジューラーを提供します。広く使われているJavaのQuartzスケジューラーを.NETに移植したものです。

Quartz.NETのインストール

QuartzパッケージとQuartz.AspNetCoreパッケージを追加します。ASP.NETとの統合機能により、スケジューラーがホストサービスとして自動的に登録されます。

# 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

ジョブの定義

IJob(または新しいバージョンのQuartzではIAsyncJob)を実装し、Executeメソッドを定義します。ジョブコンテキストから、実行時データと現在のトリガー情報を取得できます。

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");
    }
}

ASP.NET CoreへのQuartzの登録

AddQuartzを使用してスケジューラーを構成し、AddQuartzHostedServiceを使用してIHostedServiceとして実行します。ジョブとトリガーはラムダ式内で構成します。

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);

Cron式の構文

Quartzでは、6または7フィールドのcron式を使用します:seconds minutes hours day-of-month month day-of-week [year]。QuartzのcronはUnixのcronと少し異なり、秒が先頭になります。

// 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

単純なトリガー

cronの複雑さを必要としない間隔ベースのスケジュールには、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)));

Job Data Map

JobDataMapを介して、実行時パラメーターをジョブに渡します。Execute内では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]は、前のジョブインスタンスがまだ実行中の場合に、新しいジョブインスタンスが開始されるのを防ぎます。共有リソースにアクセスするジョブには不可欠です。

[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.

例外処理と再試行

ジョブのコードをtry/catchで囲んでください。JobExecutionExceptionをスローすると、Quartzにジョブを直ちに、または遅延後に再実行するよう通知できます。

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
    }
}

実践例:複数ジョブのスケジューラー

異なるスケジュールで実行される複数のジョブを持ち、すべてのジョブでDIを使用する、本番環境向けのQuartz構成です。

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 * * ?"));
});

理解度チェック

Quartz.NETのジョブに付ける[DisallowConcurrentExecution]属性には、どのような効果がありますか?

まとめ:Quartz.NETのスケジュールジョブ

重要なポイント:

  • Quartz.NET:cron、永続化、クラスタリングに対応した本番環境向けスケジューラーです
  • IJobにExecuteメソッドを実装してジョブを定義します
  • AddQuartz + AddQuartzHostedServiceで登録し、ジョブはDIに対応します
  • Cron形式:seconds minutes hours dom month dow — 秒が先頭になる点に注意してください
  • [DisallowConcurrentExecution]:再実行する前に現在の実行が完了するまで待機します
  • JobDataMapを使用して、実行時パラメーターをジョブに渡します
無料で開始

AI チューターと学ぶ C# — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
93
レッスン
346

よくある質問

「Quartz.NETのスケジュールジョブ」レッスンは無料ですか?

はい。「Quartz.NETのスケジュールジョブ」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C# Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C# Academyコースには全4レッスンが含まれています。

「Quartz.NETのスケジュールジョブ」で何を学びますか?

Quartz.NETでジョブとトリガーを定義し、cron式を使って、ASP.NET CoreのDIと統合します。 ブラウザで直接実行するハンズオンコードでC# Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

C# Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのC# Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。

「Quartz.NETのスケジュールジョブ」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このC# Academyレッスンでコードを書いて実行できますか?

はい。すべてのC# Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. IHostedServiceとBackgroundService
  2. Worker Serviceプロジェクト
  3. 定期タスクとタイマー
  4. Quartz.NETのスケジュールジョブ
← C# Academyに戻る