如何在ASP.NET Core Razor Pages项目中实现定时任务调度
ASP.NET Core Razor Pages 定时任务实现方案
下面是两种生产环境常用的实现方案,可根据自身需求选择:
方案1:内置IHostedService + Cron 轻量实现
适合不需要任务持久化、重试、管理界面的轻量化场景,仅解析Cron时需要引入轻量NuGet包NCrontab
- 首先实现通用定时任务托管服务基类:
public abstract class CronScheduledService : IHostedService, IDisposable { private Timer _timer; private readonly string _cronExpression; protected CronScheduledService(string cronExpression) { _cronExpression = cronExpression; } public Task StartAsync(CancellationToken cancellationToken) { ScheduleJob(); return Task.CompletedTask; } private void ScheduleJob() { var cron = CrontabSchedule.Parse(_cronExpression); var nextRun = cron.GetNextOccurrence(DateTime.Now); var delay = nextRun - DateTime.Now; if (delay.TotalMilliseconds < 0) delay = TimeSpan.Zero; _timer = new Timer(DoWork, null, delay, Timeout.InfiniteTimeSpan); } private void DoWork(object state) { ExecuteTaskAsync().Wait(); ScheduleJob(); } protected abstract Task ExecuteTaskAsync(); public Task StopAsync(CancellationToken cancellationToken) { _timer?.Change(Timeout.Infinite, 0); return Task.CompletedTask; } public void Dispose() { _timer?.Dispose(); } }
- 分别实现两个业务对应的任务类,直接调用已完成的业务逻辑即可:
// 邮件提醒任务 public class WeeklyReminderEmailService : CronScheduledService { // 注入你已经写好的邮件业务服务 private readonly IYourEmailService _emailService; // Cron示例:每周一9点 0 0 9 ? * MON public WeeklyReminderEmailService(IYourEmailService emailService) : base("0 0 9 ? * MON") { _emailService = emailService; } protected override async Task ExecuteTaskAsync() { await _emailService.SendWeeklyReminder(); } } // 评分任务 public class WeeklyScoreTaskService : CronScheduledService { private readonly IYourScoreService _scoreService; // Cron示例:每周日22点 0 0 22 ? * SUN public WeeklyScoreTaskService(IYourScoreService scoreService) : base("0 0 22 ? * SUN") { _scoreService = scoreService; } protected override async Task ExecuteTaskAsync() { await _scoreService.RunWeeklyScore(); } }
- 在
Program.cs里注册服务即可生效:
builder.Services.AddHostedService<WeeklyReminderEmailService>(); builder.Services.AddHostedService<WeeklyScoreTaskService>();
方案2:Hangfire 生产级实现(推荐)
适合需要任务持久化、失败自动重试、可视化管理、灵活调整调度规则的生产场景,对现有业务代码侵入性极低
- 第一步安装对应NuGet包:
Hangfire.AspNetCore+ 对应存储的包(比如用SQL Server就装Hangfire.SqlServer,用SQLite就装Hangfire.SQLite.Core) - 第二步在
Program.cs里配置Hangfire服务:
// 配置Hangfire存储 builder.Services.AddHangfire(config => config.UseSqlServerStorage(builder.Configuration.GetConnectionString("你的数据库连接字符串Key"))); // 注册Hangfire服务端 builder.Services.AddHangfireServer();
- 第三步配置中间件,可选开启管理后台:
// 放在app.MapRazorPages();之前 app.UseHangfireDashboard(); // 访问路径默认是/hangfire,可自行配置权限
- 第四步注册两个定时任务,直接调用已有的业务逻辑:
// 程序启动时注册重复任务 RecurringJob.AddOrUpdate<IYourEmailService>("weekly-reminder-email", s => s.SendWeeklyReminder(), "0 0 9 ? * MON"); // 每周一9点,可自行修改Cron表达式 RecurringJob.AddOrUpdate<IYourScoreService>("weekly-score-task", s => s.RunWeeklyScore(), "0 0 22 ? * SUN"); // 每周日22点
注意事项
- 如果用内置托管服务方案,部署在IIS时需要开启站点的「总是运行」「预加载」配置,避免IIS回收进程导致任务不执行
- Hangfire的任务会持久化到配置的存储中,应用重启、异常退出都不会丢失任务,支持自动重试,生产环境更稳定
- 已经写完的业务逻辑不需要做任何修改,直接注入到调度逻辑中调用即可
内容的提问来源于stack exchange,提问作者cbas007
相关产品推荐
相关产品推荐

