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

如何让JobDataMap的修改在Quartz.NET的其他作业上下文可见?

问题:修改Quartz.NET作业JobDataMap后无法在其他作业中生效

我有一个ReloadJob,用于修改调度器中所有其他作业的JobDataMap,但在另一个作业的上下文里获取JobDetail时,得到的是空的JobDataMap。我知道修改仅在当前上下文可见,请问是否有办法让所有调度器作业都能看到这些修改?

ReloadJob代码:

[PersistJobDataAfterExecution]
[DisallowConcurrentExecution]
public class ReloadJob : IJob
{
    public async Task Execute(IJobExecutionContext context)
    {
       try
        {
            GetJobs();
        }
        catch(Exception ex)
        {
            JobExecutionException jex = new JobExecutionException(ex, false);
            throw jex;
        }

    }

    private async void GetJobs()
    {
        IScheduler scheduler = await SchedulerRepository.Instance.Lookup("ConsoleScheduler");
        var jobGroups = scheduler.GetJobGroupNames().Result;
        foreach (string group in jobGroups)
        {
            var groupMatcher = GroupMatcher<JobKey>.GroupContains(group);
            var jobKeys = scheduler.GetJobKeys(groupMatcher).Result;
            foreach (var jobKey in jobKeys)
            {
                var detail = scheduler.GetJobDetail(jobKey).Result;
                var triggers = scheduler.GetTriggersOfJob(jobKey).Result;
                detail.JobDataMap.Put("Reload", "yes");
                foreach (ITrigger trigger in triggers)
                {
                    
                    Console.WriteLine(detail.JobType.Name);
                    Console.WriteLine(detail.JobDataMap.Get("Reload"));
                    
                }
            }
        }
    }
}

另一个作业获取JobDataMap的代码:

public async Task Execute(IJobExecutionContext context)
{
    var temp = context.JobDetail.JobDataMap;
   
}

注:[PersistJobDataAfterExecution]和[DisallowConcurrentExecution]仅在修改所在的上下文生效。


解决方案

要让修改的JobDataMap持久化到Quartz存储中,让所有作业都能读取到,你需要调用scheduler.AddJob()方法并传入true参数覆盖已存在的作业详情——直接修改从调度器获取的JobDetail只是内存副本,不会自动同步到Quartz的持久化存储。

修改后的GetJobs()方法:

private async Task GetJobs() // 替换async void为async Task,避免异步异常无法捕获
{
    IScheduler scheduler = await SchedulerRepository.Instance.Lookup("ConsoleScheduler");
    var jobGroups = await scheduler.GetJobGroupNames(); // 用await替代.Result,避免阻塞死锁
    foreach (string group in jobGroups)
    {
        var groupMatcher = GroupMatcher<JobKey>.GroupContains(group);
        var jobKeys = await scheduler.GetJobKeys(groupMatcher);
        foreach (var jobKey in jobKeys)
        {
            var detail = await scheduler.GetJobDetail(jobKey);
            // 修改JobDataMap
            detail.JobDataMap.Put("Reload", "yes");
            // 覆盖原作业,第二个参数true表示允许替换已存在的作业
            await scheduler.AddJob(detail, true);
            
            var triggers = await scheduler.GetTriggersOfJob(jobKey);
            foreach (ITrigger trigger in triggers)
            {
                Console.WriteLine(detail.JobType.Name);
                Console.WriteLine(detail.JobDataMap.Get("Reload"));
            }
        }
    }
}

额外注意事项:

  • 避免使用async void,改用async Task保证异步异常能被捕获处理
  • 用await替代.Result,防止异步操作中的阻塞和死锁问题
  • 其他作业获取最新JobDataMap时,可以选择两种方式:
    1. 从上下文的MergedJobDataMap获取(合并了作业和触发器的DataMap)
    2. 从调度器重新拉取最新的JobDetail

示例:

public async Task Execute(IJobExecutionContext context)
{
    // 方式1:获取合并后的JobDataMap
    var mergedData = context.MergedJobDataMap;
    string reloadFlag = mergedData.GetString("Reload");

    // 方式2:从调度器获取最新的JobDetail
    var latestDetail = await context.Scheduler.GetJobDetail(context.JobDetail.Key);
    string latestReloadFlag = latestDetail.JobDataMap.GetString("Reload");
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 03:40:35