stevenjin 2024-10-12 16:21 采纳率: 98%
浏览 6
已结题

quartz任务没有执行完,就执行了下一轮任务

环境:quazrtz.net实现,asp.net core mvc
一个计划分内外两层,类似大循环套小循环。当前一个内外两层循环执行完成后,依次进入下一个内外两层循环(内外两层非无限)。
1.外层:等待N分钟,开灯N分钟后关闭。再等待N分钟,进入下一步。
2.下一步:如果有内层,则:等待N分钟,开灯N分钟后关闭(等待时间与上一步的等待时间累加)。
以上有执行次数;如果没有内层,等待N分钟后,进入下一个同样的内外两层循环。

问题:没有等待外层执行完,就进入了内层。尽管加了特性[DisallowConcurrentExecution]

    public class MySchedulerFactory
    {
        /// <summary>
        /// 由CLR保证,在程序第一次使用该类之前被调用,而且只调用一次
        /// </summary>
        private static IScheduler _Scheduler = StdSchedulerFactory.GetDefaultScheduler().Result;
        public static IScheduler GetScheduler()
        {
            return _Scheduler;
        }
    }

 private void FeedingPlanSchedule()
 {
     //实例化调度器           
     NameValueCollection pars = new NameValueCollection
     {
         //线程池个数20
         ["quartz.threadPool.threadCount"] = "20",
         //scheduler名字
         ["quartz.scheduler.instanceName"] = "MyAdoJobStoreScheduler",
         //类型为JobStoreXT,事务
         ["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz",
         //数据源名称
         ["quartz.jobStore.dataSource"] = "QuartzDb",
         //使用mysql的Ado操作代理类
         ["quartz.jobStore.driverDelegateType"] = "Quartz.Impl.AdoJobStore.MySQLDelegate, Quartz",
         //数据源连接字符串
         ["quartz.dataSource.QuartzDb.connectionString"] = @"server=127.0.0.1;Database=quartzmanager;user id=root;password=123;SslMode=none;",
         //数据源的数据库
         ["quartz.dataSource.QuartzDb.provider"] = "MySql",
         //序列化类型
         ["quartz.serializer.type"] = "json",
         //自动生成scheduler实例ID,主要为了保证集群中的实例具有唯一标识
         ["quartz.scheduler.instanceId"] = "AUTO"
     };

     IScheduler scheduler = MySchedulerFactory.GetScheduler();
     //开启调度器
     scheduler.Start();

     //创建外层作业
     IJobDetail job1 = JobBuilder.Create<FeedingJob.OuterJob>()
         .WithIdentity("job1", "groupa")//名称,分组
         .Build();

     //创建外层触发器
     ITrigger trigger1 = TriggerBuilder.Create()
         .WithIdentity("trigger1", "groupa")//名称,分组
         .StartNow()//从启动的时候开始执行
         .WithSimpleSchedule(b =>
         {
             b.WithIntervalInSeconds(8)//*执行一次
              .WithRepeatCount(30);//重复执行3+1次
         })
         .StartAt(DateBuilder.FutureDate(3, IntervalUnit.Second))//3秒后执行
         .Build();

     //把外层作业,触发器加入调度器          
     var state = scheduler.ScheduleJob(job1, trigger1);

    

     //创建内层作业
     IJobDetail job2 = JobBuilder.Create<FeedingJob.InnnerJob>()
         .WithIdentity("job2", "groupa")//名称,分组
         .Build();

     //创建内层触发器
     ITrigger trigger2 = TriggerBuilder.Create()
         .WithIdentity("trigger2", "groupa")//名称,分组
         .StartNow()//从启动的时候开始执行
         .WithSimpleSchedule(b =>
         {
             b.WithIntervalInSeconds(2)//*执行一次
              .WithRepeatCount(30);//重复执行3+1次
         })
         .StartAt(DateBuilder.FutureDate(3, IntervalUnit.Second))
         .Build();
     //把内层作业,触发器加入调度器  
     scheduler.ScheduleJob(job2, trigger2);
 }

 public class FeedingJob
 {
     [DisallowConcurrentExecution]
     public class OuterJob : IJob
     {
         public Task Execute(IJobExecutionContext context)
         {
             Console.WriteLine("outer job executed:"+DateTime.Now);
             return Task.CompletedTask;
         }
     }

     [DisallowConcurrentExecution]
     public class InnnerJob : IJob
     {
         public Task Execute(IJobExecutionContext context)
         {
             Console.WriteLine("inner job executed:"+DateTime.Now);
             return Task.CompletedTask;
         } 
     }
  • 写回答

2条回答 默认 最新

  • 月下独码 Java领域新星创作者 2024-10-12 16:41
    关注

    本答案参考 多次询问 ChatGPT-3.5 后选择的最佳回答,若是满意,还请采纳,谢谢

    1. 问题分析
      • 关于[DisallowConcurrentExecution]特性未生效的可能原因
        • 调度器配置问题:虽然在作业类上添加了[DisallowConcurrentExecution]特性,但可能是调度器的某些全局配置或者任务的触发设置导致了这个特性没有按照预期工作。例如,调度器可能没有正确识别这个特性,或者在任务触发逻辑中有一些设置覆盖了这个并发执行的限制。
        • 任务关联与依赖问题:从代码结构看,外层任务和内层任务是分别创建和调度的。可能在任务的关联和依赖关系上没有正确设置。即使外层任务没有执行完,由于内层任务的触发设置独立于外层任务的执行状态,可能会导致内层任务提前执行。例如,内层任务的StartAtWithSimpleSchedule设置可能没有考虑到外层任务的执行进度。
      • 任务执行顺序逻辑问题
        • 时间间隔与执行次数的交互:在设置任务的执行时间间隔和重复次数时,可能存在逻辑漏洞。例如,外层任务的执行时间和内层任务的启动时间可能存在重叠部分,没有按照预期的顺序进行。如果外层任务的执行时间较长,而内层任务的启动时间没有正确地依赖于外层任务的完成,就会出现内层任务提前执行的情况。
    2. 解决方案建议
      • 检查调度器配置
        • 查看Quartz.NET的文档,确保调度器的配置正确支持[DisallowConcurrentExecution]特性。例如,某些版本可能需要特定的配置项来启用这个特性的正确处理。
        • 检查调度器的全局设置,如线程池的配置是否会影响任务的并发执行控制。在当前代码中,虽然设置了线程池个数为20,但可能需要调整这个数字或者其他相关的线程池参数来确保任务按照预期的顺序执行。
      • 调整任务关联与依赖关系
        • 考虑使用Quartz.NET中的作业链(Job Chaining)功能(如果支持)。这样可以明确地设置内层任务依赖于外层任务的完成,从而保证任务的执行顺序。
        • 重新审视任务的触发时间设置。例如,可以根据外层任务的实际执行进度动态地计算内层任务的启动时间。在内层任务的TriggerBuilder中,可以修改StartAt的计算方式,使其依赖于外层任务的完成时间。
      • 重新审视时间间隔与执行次数的逻辑
        • 对于外层任务和内层任务的执行时间间隔和重复次数,进行详细的计算和测试。确保内层任务的启动时间总是晚于外层任务的完成时间。可以通过添加日志输出或者调试语句来查看任务的实际执行时间,以便调整时间间隔和执行次数的设置。例如,在外层任务的Execute方法中添加更多的日志输出,记录任务的开始时间、每个步骤的执行时间以及结束时间,然后根据这些信息调整内层任务的触发设置。
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 10月20日
  • 已采纳回答 10月12日
  • 创建了问题 10月12日

悬赏问题

  • ¥60 Matlab联合CRUISE仿真编译dll文件报错
  • ¥15 脱敏项目合作,ner需求合作
  • ¥15 脱敏项目合作,ner需求合作
  • ¥30 Matlab打开默认名称带有/的光谱数据
  • ¥50 easyExcel模板 动态单元格合并列
  • ¥15 res.rows如何取值使用
  • ¥15 在odoo17开发环境中,怎么实现库存管理系统,或独立模块设计与AGV小车对接?开发方面应如何设计和开发?请详细解释MES或WMS在与AGV小车对接时需完成的设计和开发
  • ¥15 CSP算法实现EEG特征提取,哪一步错了?
  • ¥15 游戏盾如何溯源服务器真实ip?需要30个字。后面的字是凑数的
  • ¥15 vue3前端取消收藏的不会引用collectId