hangfire定时任务不执行主因是服务注册、存储配置、工作线程三者缺一;周期任务偏差多因cron时区未对齐。program.cs须完整配置addhangfire(注册存储)、addhangfireserver(启动工作线程)、usehangfiredashboard(启用仪表盘),缺一则任务卡在scheduled或404;recurringjob需显式指定timezone,避免服务器本地时区与部署环境不一致;延迟任务须用backgroundjob.schedule而非enqueue+task.delay;并发需加[disableconcurrentexecution]或分布式锁;dashboard生产环境必须实现idashboardauthorizationfilter。

Hangfire定时任务不执行,八成是服务注册、存储配置、工作线程三者缺一;周期任务跑偏,大概率是Cron时区没对齐。
Program.cs里必须配齐AddHangfire、AddHangfireServer、UseHangfireDashboard
漏掉任一环,任务就卡在Scheduled或访问/hangfire直接404。
-
AddHangfire负责注册存储(比如UseSqlServerStorage),不配 → 任务不持久,重启即丢;传错连接字符串或数据库连不上,应用启动时就会抛异常 -
AddHangfireServer必须紧跟其后,它启动后台工作线程;没这句 → 所有任务状态永远停在Enqueued/Scheduled,不会真正执行 -
UseHangfireDashboard要放在app.UseEndpoints之前;放错位置 → 路由不生效,Dashboard打不开 - 常见报错
No service for type 'Hangfire.IBackgroundJobClient',基本就是AddHangfire没调用,或被其他代码覆盖了服务注册顺序
RecurringJob.AddOrUpdate必须显式指定TimeZone
Hangfire默认按服务器本地时区解析Cron,不是UTC。开发机上写"0 0 * * *"(每天0点),部署到UTC时区的Docker容器里,实际就是北京时间早上8点执行。
- 推荐做法:用
TimeZoneInfo.FindSystemTimeZoneById("China Standard Time")显式传入时区参数 - 备选方案:统一容器时区,在Dockerfile加
ENV TZ=Asia/Shanghai && ln -snf /usr/share/zoneinfo/$TZ /etc/localtime - Cron格式是「分 时 日 月 周」,不带秒;写
"*/30 * * * * *"会静默失败,得换Hangfire.Cron扩展包
延迟任务别用Enqueue+Task.Delay,要用BackgroundJob.Schedule
BackgroundJob.Enqueue是立即入队、尽快执行;BackgroundJob.Schedule才是带延迟的,两者底层队列不同,参数语义也不同。
- 正确写法:
BackgroundJob.Schedule(() => emailService.Send("user@ex.com"), TimeSpan.FromMinutes(3)) - 错误写法:
Task.Delay(TimeSpan.FromMinutes(3)).ContinueWith(_ => BackgroundJob.Enqueue(...))——这只是主线程空等3分钟再入队,既阻塞又不可靠 - 时间精度默认最小单位是秒;传
TimeSpan.FromMilliseconds(500)没用,轮询间隔默认15秒,毫秒级调度不现实 - 注意闭包陷阱:循环中用
for (int i = 0; i Console.WriteLine(i)),最后可能全输出10
周期任务要防并发,且依赖服务生命周期正确
RecurringJob.AddOrUpdate只是挂任务,不处理并发。同一任务在多实例部署下,可能被所有节点同时触发。
- 加
[DisableConcurrentExecution]特性,或手动加分布式锁(比如Redis锁) - 泛型调用如
RecurringJob.AddOrUpdate<imyservice>(x => x.DoWork(), "...")</imyservice>,要求IMyService必须注册为Scoped或Transient;注册成Singleton容易引发状态污染 - Dashboard默认无权限控制,生产环境务必实现
IDashboardAuthorizationFilter,否则暴露敏感任务信息
最常被忽略的是时区和并发——它们不会报错,但会让任务在“看起来正常”的情况下,悄悄偏离预期时间或重复执行多次。










