Quartz.NET for C# (.NET): Complete Guide to Task Scheduling
\n\nQuartz.NET is a powerful, flexible, and widely used open-source task scheduling library for .NET applications. It allows developers to create, manage, and execute background jobs on a schedule. If you need to run code at a specific time, at a given interval, or in response to an event (like cron jobs in Linux), Quartz.NET is the right choice. The library is a port of the popular Java framework Quartz Scheduler.
\n\nWhy is it needed? In modern development, tasks often arise that should not be executed synchronously upon user request. This could be sending email newsletters, cleaning temporary files, synchronizing data with external APIs, generating reports, updating cache, and much more. Quartz.NET provides a reliable and fault-tolerant mechanism for executing such tasks. It supports persisting job state in a database (JobStore), allowing it to survive application restarts, and also supports clustering for load distribution.
\n\nUnlike simple use of System.Threading.Timer or BackgroundService, Quartz.NET offers a rich API for managing the job lifecycle, complex triggers (daily, weekly, by CRON expressions), parallel execution, event listening, and much more. This makes it the de facto standard for scheduling in the .NET ecosystem.
Installation
\nQuartz.NET is distributed via NuGet. To install, use one of the following commands in the Package Manager Console:
\n\n# Install the main package\ndotnet add package Quartz\n\n# If you need XML configuration support\ndotnet add package Quartz.Plugins\n\n# For use with Dependency Injection (recommended for ASP.NET Core)\ndotnet add package Quartz.Extensions.Hosting\n\n\nFor classic .NET Framework (e.g., .NET 4.8), use the NuGet console:
\nInstall-Package Quartz\n\n\nQuick Start: Minimal Working Example
\nLet's create a simple console application that will output "Hello, Quartz!" every 5 seconds.
\n\nusing System;\nusing System.Threading.Tasks;\nusing Quartz;\nusing Quartz.Impl;\n\nnamespace QuartzQuickStart\n{\n // 1. Create a Job\n public class HelloJob : IJob\n {\n public async Task Execute(IJobExecutionContext context)\n {\n await Console.Out.WriteLineAsync($"Hello, Quartz! Time: {DateTime.Now:HH:mm:ss}");\n }\n }\n\n class Program\n {\n static async Task Main(string[] args)\n {\n // 2. Create a scheduler factory\n StdSchedulerFactory factory = new StdSchedulerFactory();\n\n // 3. Get the scheduler\n IScheduler scheduler = await factory.GetScheduler();\n\n // 4. Start the scheduler\n await scheduler.Start();\n\n // 5. Define the Job\n IJobDetail job = JobBuilder.Create()\n .WithIdentity("myJob", "group1")\n .Build();\n\n // 6. Define the Trigger (schedule)\n ITrigger trigger = TriggerBuilder.Create()\n .WithIdentity("myTrigger", "group1")\n .StartNow()\n .WithSimpleSchedule(x => x\n .WithIntervalInSeconds(5)\n .RepeatForever())\n .Build();\n\n // 7. Register the job and trigger with the scheduler\n await scheduler.ScheduleJob(job, trigger);\n\n // 8. Wait so the console doesn't close\n await Task.Delay(TimeSpan.FromSeconds(30));\n\n // 9. Stop the scheduler\n await scheduler.Shutdown();