Zaplanowane zadania Quartz.NET
Definiuj zadania i wyzwalacze za pomocą Quartz.NET, używaj wyrażeń cron i integruj rozwiązanie z DI ASP.NET Core.
Zaplanowane zadania Quartz.NET to bezpłatna lekcja C# Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej C# Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs C# Academy zawiera 4 lekcji w sumie.
Dlaczego Quartz.NET?
Gdy potrzebujesz wyrażeń cron, trwałości zadań, klastrowania, zasad ponawiania i łańcuchów zadań — Quartz.NET zapewnia gotowy do użycia w produkcji harmonogram wykraczający poza możliwości PeriodicTimer. Jest to port popularnego harmonogramu Quartz z języka Java na platformę .NET.
Instalowanie Quartz.NET
Dodaj pakiety Quartz i Quartz.AspNetCore. Integracja z ASP.NET automatycznie rejestruje scheduler jako usługę hostowaną.
# 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.PluginsDefiniowanie zadania
Zaimplementuj IJob (lub IAsyncJob w nowszych wersjach Quartz) z metodą Execute. Kontekst zadania udostępnia dane środowiska uruchomieniowego oraz informacje o bieżącym wyzwalaczu.
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");
}
}Rejestrowanie Quartz w ASP.NET Core
Użyj AddQuartz, aby skonfigurować scheduler, oraz AddQuartzHostedService, aby uruchomić go jako IHostedService. Zadania i wyzwalacze konfiguruje się w lambdzie.
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);Składnia wyrażeń cron
Quartz używa 6- lub 7-polowego wyrażenia cron: seconds minutes hours day-of-month month day-of-week [year]. Cron w Quartz nieco różni się od crona w systemie Unix — sekundy znajdują się na początku.
// 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 expressionsProste wyzwalacze
W przypadku harmonogramów opartych na interwałach, które nie wymagają złożoności crona, użyj prostych wyzwalaczy z 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
Przekazuj parametry środowiska uruchomieniowego do zadań za pomocą JobDataMap. Uzyskuj do nich dostęp wewnątrz Execute przez 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] zapobiega uruchomieniu nowej instancji zadania, gdy poprzednia nadal działa. Jest to niezbędne w przypadku zadań uzyskujących dostęp do współdzielonych zasobów.
[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.Obsługa wyjątków i ponawianie
Umieść kod zadania w bloku try/catch. Rzuć JobExecutionException, aby poinformować Quartz, że ma natychmiast ponowić zadanie lub zrobić to po opóźnieniu.
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
}
}Praktyczny przykład: scheduler z wieloma zadaniami
Produkcyjna konfiguracja Quartz z wieloma zadaniami wykonywanymi według różnych harmonogramów, korzystającymi ze wstrzykiwania zależności dla usług.
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 * * ?"));
});Szybkie sprawdzenie
Co robi atrybut [DisallowConcurrentExecution] umieszczony na zadaniu Quartz.NET?
Podsumowanie: zaplanowane zadania Quartz.NET
Najważniejsze informacje:
- Quartz.NET: gotowy do użycia w produkcji scheduler z obsługą crona, trwałości i klastrowania
- Definiuj zadania, implementując IJob z metodą Execute
- Rejestruj za pomocą AddQuartz + AddQuartzHostedService; zadania obsługują DI
- Format crona: seconds minutes hours dom month dow — sekundy znajdują się na początku
[DisallowConcurrentExecution]: przed ponownym uruchomieniem zaczekaj na zakończenie bieżącego wykonania- Używaj JobDataMap do przekazywania parametrów środowiska uruchomieniowego do zadań
Ucz się C# dzięki korepetycjom AI — za darmo
Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.
- Kursy
- 93
- Lekcje
- 346
Często zadawane pytania
Czy lekcja „Zaplanowane zadania Quartz.NET” jest bezpłatna?
Tak — pełny tekst „Zaplanowane zadania Quartz.NET” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu C# Academy, przejdź na CoddyKit PRO. Kurs C# Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Zaplanowane zadania Quartz.NET”?
Definiuj zadania i wyzwalacze za pomocą Quartz.NET, używaj wyrażeń cron i integruj rozwiązanie z DI ASP.NET Core. Ćwiczysz C# Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć C# Academy?
Nie wymagamy żadnego doświadczenia. C# Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „Zaplanowane zadania Quartz.NET”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji C# Academy?
Tak. Każda lekcja C# Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- IHostedService i BackgroundService
- Projekty Worker Service
- Zadania okresowe i timery
- Zaplanowane zadania Quartz.NET