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

如何为Quartz.NET设置长时任务的非工作时段启停及重启规则?

Quartz.NET 实现定时启停+未完成次日重启方案

核心思路

Quartz.NET的核心是调度任务启动,没有直接的任务停止机制,所以要结合任务内部的控制逻辑+Quartz调度规则实现需求:

  1. 用Cron表达式配置每日启动时间
  2. 任务内部监听停止时间,到点主动终止执行
  3. 记录任务执行状态,次日启动时自动续跑未完成部分

具体实现步骤

1. 配置每日启动调度

通过Quartz的Job和Trigger配置,用Cron表达式指定每日启动时间(比如每天20:00启动):

// 注册Quartz服务
services.AddQuartz(q =>
{
    // 注册长耗时任务
    q.AddJob<LongRunningJob>(opts => opts.WithIdentity("LongRunningJob"));
    
    // 配置每日20:00启动的Trigger
    q.AddTrigger(opts => opts
        .ForJob("LongRunningJob")
        .WithIdentity("DailyStartTrigger")
        .WithCronSchedule("0 0 20 * * ?")); // Cron表达式:每天20点整执行
});

// 集成IHostedService,确保程序关闭时等待任务完成
services.AddQuartzHostedService(q => q.WaitForJobsToComplete = true);

2. 任务内部实现启停控制

在Job的执行逻辑里,加入停止时间检查,并记录执行进度,确保到点能终止、次日能续跑:

// 标记禁止并发执行,避免同一任务重复启动
[DisallowConcurrentExecution]
public class LongRunningJob : IJob
{
    private readonly IJobStatusStore _statusStore; // 自定义状态存储(数据库/Redis均可)
    private readonly TimeOnly _dailyStopTime = TimeOnly.Parse("08:00"); // 每日停止时间

    public LongRunningJob(IJobStatusStore statusStore)
    {
        _statusStore = statusStore;
    }

    public async Task Execute(IJobExecutionContext context)
    {
        // 读取上次未完成的任务进度
        var lastStatus = await _statusStore.GetLatestStatusAsync();
        int currentProgress = lastStatus?.Progress ?? 0;

        // 循环执行任务,每一步检查是否到停止时间
        while (currentProgress < 100)
        {
            var now = TimeOnly.FromDateTime(DateTime.Now);
            // 到达停止时间,保存进度后终止
            if (now >= _dailyStopTime)
            {
                await _statusStore.UpdateStatusAsync(currentProgress, isCompleted: false);
                return;
            }

            // 执行单次任务单元(比如处理一批数据)
            await ProcessSingleBatchAsync(currentProgress);
            currentProgress += 10; // 假设每次完成10%进度
        }

        // 任务完全完成,清除状态记录
        await _statusStore.ClearStatusAsync();
    }

    private async Task ProcessSingleBatchAsync(int currentProgress)
    {
        // 替换为实际业务逻辑,比如数据同步、文件处理等
        await Task.Delay(TimeSpan.FromMinutes(5)); // 模拟耗时操作
    }
}

3. 次日自动续跑逻辑

因为已经通过Cron配置了每日20:00自动启动Job,次日启动时,Job会自动读取上次保存的进度,从断点处继续执行,直到任务完成或再次到达停止时间。

关键注意事项

  • 状态存储实现:需要自己实现简单的状态存储(比如数据库表),字段至少包含进度值、是否完成,确保重启后能恢复进度
  • 异常处理:在任务执行过程中捕获异常,及时保存当前进度,避免异常导致进度丢失
  • 资源释放:任务终止前要确保释放所有占用的资源(比如数据库连接、文件句柄等)

内容的提问来源于stack exchange,提问作者JHJ

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 21:04:52