UTimer 2.0.0
dotnet add package UTimer --version 2.0.0
NuGet\Install-Package UTimer -Version 2.0.0
<PackageReference Include="UTimer" Version="2.0.0" />
<PackageVersion Include="UTimer" Version="2.0.0" />
<PackageReference Include="UTimer" />
paket add UTimer --version 2.0.0
#r "nuget: UTimer, 2.0.0"
#:package UTimer@2.0.0
#addin nuget:?package=UTimer&version=2.0.0
#tool nuget:?package=UTimer&version=2.0.0
UTimer
Lightweight, dependency-injection friendly job scheduler for .NET Core applications. Configure processes and run scheduled jobs in the background — one-shot, at a specific time, recurring (fixed period or cron), and continuations.
Install
dotnet add package UTimer
Setup
var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddUTimer(
maxDegreeOfParallelism: 20, // queued jobs running concurrently
maxQueueSize: 1000, // bounded queue; enqueue waits when full
defaultTimeZone: TimeZoneInfo.Local); // cron time zone; null (default) = UTC
var host = builder.Build();
await host.StartAsync();
All jobs are identified by a string job id.
One-shot jobs
// After a delay (runs exactly once)
string id = JobCreator.CreateJob(() => Console.WriteLine("merhaba"), TimeSpan.FromSeconds(5));
// Async — the returned Task is awaited
JobCreator.CreateJob(async () => await File.WriteAllTextAsync("log.txt", "x"));
// Resolve a service from a fresh DI scope
JobCreator.CreateJob<IMailService>(m => m.SendAsync("a@b.c"));
// Control by id
JobCreator.CancelJob(id); // cancel before it starts (true if cancelled)
await JobCreator.WaitAsync(id); // wait for completion
At a specific time
JobCreator.CreateJobAt(() => Raporla(), new DateTime(2026, 9, 5, 14, 30, 0)); // local
JobCreator.CreateJobAt<IMailService>(m => m.GonderAsync(), DateTime.UtcNow.AddHours(3));
Past times run immediately. DateTimeKind.Unspecified is treated as local.
Recurring jobs
// Fixed period: first tick immediately, then "period" between the END of one
// run and the START of the next — ticks never overlap.
string id = JobCreator.CreateRecurringJob(() => Temizle(), TimeSpan.FromMinutes(10));
// Cron (uses AddUTimer's defaultTimeZone; pass an explicit TimeZoneInfo to override)
JobCreator.CreateRecurringJob(() => Raporla(), "0 3 * * *");
JobCreator.CreateRecurringJob(() => Raporla(), "30 9 * * 1", TimeZoneInfo.Local);
// Seconds precision (6-field cron)
JobCreator.CreateRecurringJob(() => Tick(), "*/30 * * * * *",
cronFormat: UTimer.Cronos.CronFormat.IncludeSeconds);
// With a DI service (fresh scope per tick)
var job = JobCreator.CreateRecurringJob<ICacheService>(c => c.Refresh(), TimeSpan.FromHours(1));
JobCreator.CancelJob(job); // stops the repetition
If the expression body returns a Task (e.g. x => x.RefreshAsync()), it is
awaited; a slow tick delays the next one instead of overlapping. A throwing
iteration is logged and the loop continues.
Continuations
// Enqueue the parent job and capture its Job ID
string parentJobId = JobCreator.CreateJob(() => Console.WriteLine("Parent job running..."));
// Queue a continuation job that runs after the parent job finishes
string childJobId = JobCreator.ContinueWith(
parentJobId,
() => Console.WriteLine("Child continuation job running...")
);
Semantics (OnCompletion): the child runs when the parent finishes, whether the
parent succeeded or failed. A canceled parent cancels its children.
Continuations can be chained (ContinueWith(childJobId, ...)) and work on
queued jobs too. Attach them while the parent is pending or within the
one-minute completion retention window.
Background queue
var creator = host.Services.GetRequiredService<JobCreator>();
string id = await creator.EnqueueAsync<IOrderService>(s => s.ProcessAsync(order));
Bounded-channel queue drained by a BackgroundService with a concurrency
semaphore. CancelJob(id) works until the job starts running.
Shutdown
On host.StopAsync() (or provider disposal): pending jobs are canceled,
running jobs are awaited. Jobs that ignore their CancellationToken can delay
shutdown indefinitely — use the Func<CancellationToken, Task> overloads for
cancellable work.
Limitations
- In-memory only. A process crash loses pending jobs, continuations and recurring registrations. Re-register recurring jobs at startup; if you need durability, retries and persisted continuations, use Hangfire or Quartz.NET.
- The static
JobCreatorfacade requires the host to be started (AddUTimer+StartAsync); with multiple hosts in one process the last registered one wins.
License
MIT — see LICENSE. Includes vendored Cronos sources (MIT).
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.Extensions.DependencyInjection (>= 10.0.11)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.11)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.