stevenjin 2024-10-15 11:00 采纳率: 98%
浏览 0
已结题

Quartz.NET多个计划时遇到的问题

Quartz.NET
由于要同时执行多个计划,于是想再复制一份FeedingSchedule,但报错说数据库哪重复了
1.多个计划,怎样指向同一数据库
2.多个计划,怎样避免并发执行同一个job(我用了锁,不知可行吗?)


private async Task FeedingSchedule()
{
    await Task.Run(() => {
        //实例化调度器           
        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"
        };

        //实例化调度器
        ISchedulerFactory schedulefactory = new StdSchedulerFactory(pars);
        IScheduler scheduler = schedulefactory.GetScheduler().Result;
        //开启调度器
        scheduler.Start();

        List<Feeding> lstFeeding = new List<Feeding>();
        lstFeeding.Add(new Feeding()
        {
            PlanID = 1,
            Interval = 2,
            IsManual = true,
            ParamID = "13024",
            PhaseTime = 2,
            PlanState = 3,
            Step = 1,
            Times = 3,
            Wait = 4,
            lstSubPlan = new List<SubPlan>() {
                  new SubPlan()
                  {
                    Interval = 1,
                    Times = 2,
                  },
                  new SubPlan()
                  {
                    Interval = 3,
                    Times = 4,
                  }
            }
        });

        lstFeeding.Add(new Feeding()
        {
            PlanID = 1,
            Interval = 2,
            IsManual = true,
            ParamID = "13025",
            PhaseTime = 2,
            PlanState = 3,
            Step = 2,
            Times = 3,
            Wait = 2,
            lstSubPlan = new List<SubPlan>() {
            new SubPlan()
            {
                Interval = 2,
                Times = 2,
            },
           new SubPlan()
           {
             Interval = 3,
             Times = 4,
           }
         }
        });

        foreach (var feeding in lstFeeding)
        //for (int i = 0; i < 10; i++)
        {
            JobKey firstJobKey = JobKey.Create("FirstJob", "Pipeline");
            JobKey secondJobKey = JobKey.Create("SecondJob", "Pipeline");
            JobKey thirdJobKey = JobKey.Create("ThirdJob", "Pipeline");

            // Create job and trigger
            IJobDetail firstJob = JobBuilder.Create<FeedingJob.OuterJob>()
            .WithIdentity(firstJobKey)
            .UsingJobData("outerSays", "Hello World,I'm outSide!")
            //.StoreDurably(true)
            .Build();

            IJobDetail secondJob = JobBuilder.Create<FeedingJob.InnnerJob>()
            .WithIdentity(secondJobKey)
            .UsingJobData("innerSays", "Hello World,I'm inSide1!")
            .UsingJobData("executeNext", "false")
            .StoreDurably(true)//指示Quartz在Job成为“孤儿”时不要删除Job(当Job不再有Trigger引用它时),按顺序触发关键
            .Build();

            IJobDetail thirdJob = JobBuilder.Create<FeedingJob.InnnerJob>()
            .WithIdentity(thirdJobKey)
            .UsingJobData("innerSays", "Hello World,I'm inSide2!")
            .UsingJobData("executeNext", "true")
            .StoreDurably(true)
            .Build();

            ITrigger firstJobTrigger = TriggerBuilder.Create()
            .WithIdentity("Trigger", "Pipeline")
            .WithSimpleSchedule(x => x
            .WithMisfireHandlingInstructionFireNow()
            .WithIntervalInSeconds(4)
            .WithRepeatCount(0)).StartAt(DateTime.Now.AddSeconds(1))
            .Build();

            //创建计划链表
            JobChainingJobListener listener = new JobChainingJobListener("JobLink");
            listener.AddJobChainLink(firstJobKey, secondJobKey);
            listener.AddJobChainLink(secondJobKey, thirdJobKey);

            //将trigger监听器注册到调度器
            //scheduler.ListenerManager.AddTriggerListener(new CustomTriggerListener());
            scheduler.ListenerManager.AddJobListener(listener, GroupMatcher<JobKey>.GroupEquals("Pipeline"));

            // Run it all in chain
            scheduler.Start();
            scheduler.ScheduleJob(firstJob, firstJobTrigger);
            scheduler.AddJob(secondJob, false, true);
            scheduler.AddJob(thirdJob, false, true);

            int subPlanWait = feeding.lstSubPlan.Sum(o => o.Interval * o.Times);
            int totalWait = (feeding.Wait + feeding.PhaseTime) * feeding.Interval + subPlanWait;
            Thread.Sleep(totalWait * 1000);
        }


        //Console.ReadLine();
        //scheduler.Shutdown();
        //Console.WriteLine("Scheduler shutdown.");
        //Console.WriteLine(history);
        //Console.ReadLine();
    });
  
}


public class FeedingJob
{
    [DisallowConcurrentExecution]
    public class OuterJob : IJob
    {
        private static object _lockOuterJob = new object();
        public Task Execute(IJobExecutionContext context)
        {
            lock (_lockOuterJob)
            {
                JobKey jobKey = context.JobDetail.Key;
                JobDataMap dataMap = context.JobDetail.JobDataMap;
                string jobSays = dataMap.GetString("outerSays");
                Console.WriteLine($"Outer job executed[{jobKey}]:{DateTime.Now},Content:{jobSays}");
                Thread.Sleep(1000);
                return Task.CompletedTask;
            }

        }
    }

    [DisallowConcurrentExecution]
    public class InnnerJob : IJob
    {
        private static object _lockInnnerJob = new object();
        public Task Execute(IJobExecutionContext context)
        {
            lock (_lockInnnerJob)
            {
                JobKey jobKey = context.JobDetail.Key;
                JobDataMap dataMap = context.JobDetail.JobDataMap;
                string jobSays = dataMap.GetString("innerSays");
                string executeNext = dataMap.GetString("executeNext");
                Console.WriteLine($"Innner job executed[{jobKey}]:{DateTime.Now},Content:{jobSays},executeNext:{executeNext}");
                Thread.Sleep(1000);
            }             
            return Task.CompletedTask;
        } 
    }
}
  • 写回答

1条回答 默认 最新

  • 关注

    上午好☀️☀️☀️️
    本答案参考ChatGPT-3.5

    quartz.db.DataSource.你可以在你的代码中添加以下行来解决这个问题:

    using System.Data.SqlClient;
    
    // 使用SQLite作为数据源
    var connection = new SqlConnection(@"Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;");
    connection.Open();
    

    这将确保数据库中的"Feedings"列为空,并且在调用Feeding schedules()函数时不会引发任何错误。

    另外,您还可以考虑以下两种方式来避免并发执行相同的任务:

    1. 实现多线程或多进程:您可以使用线程池或异步I/O等技术来创建多个任务,并在需要时通过适当的锁同步它们。但是需要注意的是,多线程或多进程可能会增加系统的负载和资源消耗。

    2. 使用队列:可以将任务放入队列,然后依次处理这些任务。这种方法的优点是它可以更好地控制任务的执行顺序,从而避免并发执行相同任务的情况。但是缺点是,如果您无法正确地管理队列的大小,可能会导致溢出或内存问题。此外,队列也可以用于存储临时的数据或日志记录等非实时的任务。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 10月15日
  • 已采纳回答 10月15日
  • 创建了问题 10月15日

悬赏问题

  • ¥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