Download Latest Version v4.1.1 source code.zip (9.1 MB) Google Add to Preferred Sources
Home / v3.21.0
Name Modified Size InfoDownloads / Week
Parent folder
Quartz.NET-3.21.0.zip 2026-09-14 51.5 MB
README.md 2026-09-09 3.6 kB
v3.21.0 source code.tar.gz 2026-09-09 5.5 MB
v3.21.0 source code.zip 2026-09-09 6.2 MB
Totals: 4 Items   63.3 MB 0

Quartz.NET 3.21.0 carries the three fixes held back from 3.20.1 because each needed a small addition to the public surface or changed what a running scheduler does. All three were found while 4.0 was being finished; each is as old as 3.x. The public API grows by two interfaces on one class and nothing else; the schema is 3.20's. Three of the changes alter behaviour, each marked Behavior change worth noting below.

:::shell
dotnet add package Quartz --version 3.21.0

What changed

  • ResumeAll clears every paused trigger group, not only the ones with triggers — the persistent store resumed the groups it found in QRTZ_TRIGGERS and then deleted only its all-groups marker, so a group paused while it held no triggers kept its QRTZ_PAUSED_TRIGGER_GRPS row and went on pausing whatever was scheduled into it afterwards. Pausing a group before anything is scheduled into it is a documented use of the exact-name matcher, so this was a row the store wrote on purpose and could not take back. The trailing delete now takes every group, as RAMJobStore has always done. (#3721, [#3742], port of f76b04a468)
  • Behavior change worth noting: a group paused while empty no longer survives ResumeAll.
  • A job store closes its lock handler when it shuts down — RedisSemaphore opened a ConnectionMultiplexer on the first lock and kept it, with its heartbeat, for the life of the process, because nothing on the store's shutdown path reached the lock handler and ISemaphore had no member that meant "we are done". On a branch that targets netstandard2.0 and net462 an interface cannot gain a default member, so JobStoreSupport.Shutdown now disposes a lock handler that implements IAsyncDisposable or IDisposable, after the misfire handler, the cluster manager and the connection manager have stopped, logging and continuing if that throws; RedisSemaphore implements both and closes the multiplexer it opened. (#3721, [#3742], port of [#3639])
  • Behavior change worth noting: a custom ISemaphore that implements either interface is now disposed at shutdown.
  • A configured wait longer than the platform's timer ceiling is refused where it is set — Task.Delay refuses anything longer than about 49.7 days on .NET and about 24.9 days on .NET Framework, with an ArgumentOutOfRangeException naming a parameter called delay, and every duration Quartz waits out that way was accepted unchecked and reported later from wherever the wait happened. MisfireHandlerFrequency, MisfireThreshold (when it is also the handler's sleep), ClusterCheckinInterval, DbRetryInterval, TransientRetryInterval, the row-lock handlers' RetryPeriod, StartDelayed's argument and QuartzHostedServiceOptions.StartDelay now name the setting, the ceiling and the value at configuration time. The ceiling is per target framework, held to what Task.Delay actually accepts by a test. (#3721, [#3742], port of [#3577])
  • Behavior change worth noting: a value past the ceiling now fails at configuration rather than later.

Public API — additive only

  • Quartz.Extensions.Redis: RedisSemaphore implements IAsyncDisposable and IDisposable.

Upgrading

dotnet add package Quartz --version 3.21.0. Nothing to migrate. The 4.0 line is the current major; the 4.x migration guide is the way there, and 4.0.1 made the upgrade one a dependency bot can offer.

Full changelog: https://github.com/quartznet/quartznet/compare/v3.20.1...v3.21.0

Source: README.md, updated 2026-09-09