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

如何按需调度带定时器的方法调用 实现条件触发后48小时执行一次

条件触发的48小时单次调度实现方案

需求拆解

  • 触发时机:自定义业务条件满足时发起调度请求
  • 执行规则:对应业务方法调度完成后48小时内仅可执行1次,重复触发调度也不会重复执行
  • 生命周期:调度场景可无限次创建、执行,无次数上限

Quartz.NET落地实现

前置准备

先创建调度执行记录表,存储在共享存储(数据库/Redis均可),核心字段如下:

  • ScheduleKey:调度唯一标识,可按业务场景编码_业务主键规则生成,用于唯一区分不同的调度场景
  • ExecuteStatus:调度状态(待执行/已执行/执行失败)
  • LastExecuteTime:最近一次实际执行时间

调度创建逻辑

当业务条件满足时,执行以下流程:

  1. 按规则生成当前场景的ScheduleKey
  2. 查询调度记录:若存在对应ScheduleKey的记录,且LastExecuteTime距当前时间小于48小时,直接返回,不创建新调度
  3. 若不存在符合条件的记录,新增待执行状态的调度记录
  4. 调用Quartz.NET创建一次性调度任务:
// 绑定调度标识到Job参数
IJobDetail businessJob = JobBuilder.Create<YourTargetJob>()
    .WithIdentity($"job_{scheduleKey}", "custom_schedule_group")
    .UsingJobData("schedule_key", scheduleKey)
    .Build();

// 触发器设为立即执行,可根据需求调整为延迟触发
ITrigger jobTrigger = TriggerBuilder.Create()
    .WithIdentity($"trigger_{scheduleKey}", "custom_schedule_group")
    .StartNow()
    .Build();

await scheduler.ScheduleJob(businessJob, jobTrigger);

Job执行逻辑(核心幂等控制)

Job执行时先做状态校验,避免重复执行:

public class YourTargetJob : IJob
{
    public async Task Execute(IJobExecutionContext context)
    {
        string scheduleKey = context.JobDetail.JobDataMap.GetString("schedule_key");
        // 分布式场景下此处需加行锁/分布式锁,避免并发问题
        var scheduleRecord = await _dbContext.ScheduleRecords
            .FirstOrDefaultAsync(r => r.ScheduleKey == scheduleKey);

        // 校验不通过直接返回
        if (scheduleRecord == null 
            || scheduleRecord.ExecuteStatus != ExecuteStatus.Pending
            || (scheduleRecord.LastExecuteTime.HasValue 
                && DateTime.Now.Subtract(scheduleRecord.LastExecuteTime.Value).TotalHours < 48))
        {
            return;
        }

        // 先更新状态再执行业务逻辑,避免异常导致重复执行
        scheduleRecord.ExecuteStatus = ExecuteStatus.Completed;
        scheduleRecord.LastExecuteTime = DateTime.Now;
        await _dbContext.SaveChangesAsync();

        // 执行目标业务方法
        await YourBusinessMethod();
    }
}

异常处理

  • 若业务方法执行失败需要重试,可在Job内直接加重试逻辑,不要新建调度,避免突破48小时单次的限制
  • 若不需要重试,可将调度记录标记为失败,后续业务条件再次满足时可自动创建新调度,只要距上次执行超过48小时即可

轻量场景替代方案

如果是单体应用,不需要分布式调度能力,可直接用ASP.NET Core自带的IHostedService+内存队列实现,核心逻辑和上述方案一致,仅需将Quartz.NET的调度替换为后台任务轮询队列执行即可,无需引入额外组件。

注意事项

  • 分布式部署场景必须使用共享存储存储调度记录,查询和更新状态时加锁,避免多实例重复执行
  • 历史调度记录可定期归档,不影响新调度的正常创建

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 22:36:04