使用Hangfire在.NET9中实现可靠定时任务的最佳实践
Hangfire是.NET生态成熟的后台任务框架,支持即时、延迟、周期及串联任务,并提供可视化Dashboard。在.NET9中配置简单,测试可用内存存储,生产推荐SQLServer或Redis持久化。自动重试、队列隔离、分布式协调等特性保障可靠性,适合搭建轻量级定时任务系统。
.NET 9 来了,后台任务调度和定时任务管理又迎来了一波显著的体验升级。这篇文章就来聊聊如何将这个版本与 Hangfire 结合起来,搭建一套可靠又直观的定时任务系统——从项目搭建到生产部署,把关键环节都过一遍。

一、Hangfire 简介
Hangfire 是 .NET 生态里比较成熟的后台任务框架,它的能力覆盖了日常开发中的大部分需求:
- Fire-and-Forget:丢进去就跑,跑完就忘的任务
- Delayed:到点再跑的延迟任务
- Recurring:按周期重复执行的定时任务
- Continuations:任务之间串联执行的链条
- Dashboard 可视化:一个面板就能看到所有任务的状态和失败原因
为什么推荐它?核心优势其实很实在:
- 不需要额外的后台服务,直接跑在 ASP.NET Core 进程里就行。
- 支持多种持久化存储,SQL Server、Redis、MongoDB 都能用。
- 任务执行失败会自动重试,容错性不错。
- 扩展性也够用,内置依赖注入、日志、分布式任务支持。
二、创建 .NET 9 项目并安装依赖
先创建一个 .NET 9 Web API 项目:
dotnet new web -n HangfireNet9Demo cd HangfireNet9Demo
然后安装 Hangfire 以及一个内存存储(测试阶段够用了):
dotnet add package Hangfire dotnet add package Hangfire.MemoryStorage
如果准备上生产,建议换成 SQL Server:
dotnet add package Hangfire.SqlServer
三、配置 Hangfire
配置入口在 Program.cs,.NET 9 推荐走最小 API 风格,简洁明了:
using Hangfire;
using Hangfire.MemoryStorage;
using Hangfire.Common;
var builder = WebApplication.CreateBuilder(args);
// 配置 Hangfire 服务
builder.Services.AddHangfire(config =>
{
// 测试环境用内存存储
config.UseMemoryStorage();
// 生产环境推荐:
// config.UseSqlServerStorage(builder.Configuration.GetConnectionString("HangfireDb"));
});
builder.Services.AddHangfireServer();
var app = builder.Build();
// 启用 Hangfire Dashboard,默认路径 /hangfire
app.UseHangfireDashboard();
// 根路由测试
app.MapGet("/", () => "Hangfire with .NET 9 is running...");
四、创建定时任务
1. Fire-and-Forget(立即执行任务)
app.Lifetime.ApplicationStarted.Register(() =>
{
BackgroundJob.Enqueue(() => Console.WriteLine("立即执行的任务"));
});
2. Delayed(延迟任务)
app.Lifetime.ApplicationStarted.Register(() =>
{
BackgroundJob.Schedule(() => Console.WriteLine("延迟 1 分钟执行"), TimeSpan.FromMinutes(1));
});
3. Recurring(周期任务)
周期任务在实际项目中经常用来做定时报告、邮件推送或数据清理。写法如下:
app.Lifetime.ApplicationStarted.Register(() =>
{
var recurringJobManager = app.Services.GetRequiredService();
recurringJobManager.AddOrUpdate(
"say-hello-job",
Job.FromExpression(() => Console.WriteLine("Hello Hangfire .NET 9!")),
"*/1 * * * *", // 每分钟执行
new RecurringJobOptions { TimeZone = TimeZoneInfo.Local }
);
});
几个细节需要注意:
- Cron 表达式要用字符串形式传进去。
Job.FromExpression的作用是让 Hangfire 能序列化方法调用,保证任务可靠记录。RecurringJobOptions里可以配置时区、队列等参数,很灵活。
五、任务监控与管理
Hangfire 自带的 Dashboard 算是一个亮点,它能直观看到:
- 任务执行历史
- 失败的任务详情
- 自动重试的进度
- 各队列的状态
默认访问地址:
http://localhost:5000/hangfire
生产环境里别忘了加上身份验证:
app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
Authorization = new[] { new MyAuthorizationFilter() }
});
六、生产环境注意事项
- 持久化存储:内存存储只适合开发和调试,生产一定要换成 SQL Server 或 Redis,否则重启后任务就丢了。
- 任务重试:Hangfire 默认会重试 10 次,如果觉得太多,可以用
[AutomaticRetry(Attempts = 5)]来调整。 - 队列隔离:如果任务有轻重缓急,可以设置不同的队列,避免长任务把短任务堵死。
- 分布式任务:多台服务器部署时,只要共享同一个数据库,Hangfire 会自动协调任务执行,不会出现重复执行的问题。
- 日志与监控:最好结合
ILogger或第三方监控系统,把每个任务的执行情况记录下来,排查问题时省心很多。
七、完整 Program.cs 示例 (.NET 9)
using Hangfire;
using Hangfire.MemoryStorage;
using Hangfire.Common;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHangfire(config => config.UseMemoryStorage());
builder.Services.AddHangfireServer();
var app = builder.Build();
app.UseHangfireDashboard();
app.MapGet("/", () => "Hangfire with .NET 9 is running...");
// Fire-and-Forget + Delayed + Recurring 集中注册
app.Lifetime.ApplicationStarted.Register(() =>
{
BackgroundJob.Enqueue(() => Console.WriteLine("立即执行的任务"));
BackgroundJob.Schedule(() => Console.WriteLine("延迟 1 分钟执行"), TimeSpan.FromMinutes(1));
var recurringJobManager = app.Services.GetRequiredService();
recurringJobManager.AddOrUpdate(
"say-hello-job",
Job.FromExpression(() => Console.WriteLine("Hello Hangfire .NET 9!")),
"*/1 * * * *",
new RecurringJobOptions { TimeZone = TimeZoneInfo.Local }
);
});
app.Run();
✅ 总结
- Hangfire + .NET 9 的组合提供了一个轻量级、有可视化面板且足够可靠的定时任务方案。
- 内存存储适合用来快速验证想法,生产环境务必换成持久化存储。
- Cron 表达式、Job 表达式、队列与重试机制这几个核心概念搞清楚了,大部分场景都能应对。
- Dashboard 让你随时掌握任务执行状态,心里有数。
Windows 10 是一款微软推出的经典操作系统,拥有硬件兼容性与多任务处理能力。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。
极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。
















