You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 13:45:03