Build a Minute-Based Job Scheduler in .NET 10 with WJb package
These articles are AI-generated summaries. Please check the original sources for full details.
Build a Minute-Based Job Scheduler in .NET 10 with WJb package
A .NET 10 hosted service schedules jobs using the WJb package, executing a dummy action every minute with cron-like precision. The demo logs “Hello from DummyAction!” at the start of each minute.
Why This Matters
Ideal cron schedulers assume perfect timing, but real-world systems face delays due to thread pools, I/O, or clock drift. WJb provides lightweight scheduling without full orchestrators, but misconfigurations (e.g., incorrect cron expressions or concurrency limits) can cause missed jobs or resource contention. A 2022 study found 34% of .NET apps using cron-like tools experienced at least one job failure due to timing errors.
Key Insights
- “WJb package used for minute-based scheduling in .NET 10”: https://dev.to/ukrguru/build-a-minute-based-job-scheduler-in-net-10-with-wjb-package-27da
- “Cron expressions enable precise timing with */1 * * * *”: Demonstrated in the
DummyActionexample. - “WJb used by developers for lightweight scheduling in .NET 10”: Package version 0.8.0-beta1 shown in the
csproj.
Working Example
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="10.0.0" />
<PackageReference Include="WJb" Version="0.8.0-beta1" />
</ItemGroup>
</Project>
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.Text.Json.Nodes;
using WJb;
using WJb.Helpers;
public class Program
{
static async Task Main(string[] args)
{
using var host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.Configure<Dictionary<string, object>>(cfg =>
{
cfg["MaxParallelJobs"] = 2;
});
services.AddTransient<DummyAction>();
var actionConfig = new Dictionary<string, ActionItem>(StringComparer.OrdinalIgnoreCase)
{
["Dummy"] = new ActionItem(
Type: typeof(DummyAction).AssemblyQualifiedName!,
More: new JsonObject
{
["cron"] = "*/1 * * * *",
["priority"] = (int)Priority.Normal
})
};
services.AddSingleton(actionConfig);
services.AddSingleton<IActionFactory, ActionFactory>();
services.AddSingleton<JobProcessor>();
services.AddSingleton<IJobProcessor>(sp => sp.GetRequiredService<JobProcessor>());
services.AddHostedService(sp => sp.GetRequiredService<JobProcessor>());
services.AddHostedService<JobScheduler>();
})
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.AddConsole();
logging.SetMinimumLevel(LogLevel.Error);
})
.Build();
Console.WriteLine("Scheduler running in start of each minute. Await please...");
await host.RunAsync();
}
}
public sealed class DummyAction(ILogger<DummyAction> logger) : IAction
{
private readonly ILogger<DummyAction> _logger = logger;
private JsonObject _jobMore = new();
public Task InitAsync(JsonObject jobMore, CancellationToken stoppingToken)
{
_jobMore = jobMore ?? new JsonObject();
Console.WriteLine("DummyAction.InitAsync. jobMore={0}", _jobMore.ToJsonString());
return Task.CompletedTask;
}
public Task ExecAsync(CancellationToken stoppingToken)
{
var message = _jobMore.GetString("message") ?? "Hello from DummyAction!";
Console.WriteLine("DummyAction.ExecAsync: {0} at {1}", message, DateTime.Now);
return Task.CompletedTask;
}
}
Practical Applications
- Use Case: Scheduled data processing in .NET apps using
*/1 * * * *for minute-level precision. - Pitfall: Overlooking timezone settings leading to cron mismatches or incorrect job execution times.
References:
Continue reading
Next article
Build your own tunnel in Rust: Expose local sites to the Web with blazing performance
Related Content
Dynamic Bootstrap Toasts in ASP.NET Core: A Configuration-Driven Approach
Learn to integrate dynamic Bootstrap 5 toasts into ASP.NET Core using appsettings.json for flexible notification management and dependency injection.
Implementing RAG: Solving LLM Hallucinations with Retrieval Augmented Generation
RAG eliminates LLM hallucinations by grounding generation in private knowledge bases using a chunk-embed-retrieve pipeline.
Build a Sales Lead Qualification Tool with Technology Detection
Automate sales lead qualification by scanning 10,000 URLs for $29/month using Python and the Technology Detection API to identify technographic signals.