Quartz调度器:如何将自定义对象作为JobParameter传递?

22

我计划编写一个ASP.NET页面以按需触发作业。目前,我正在使用SimpleTrigger类来触发作业,但是__Trigger类中没有支持在JobParameters中将对象类型作为值的选项。据我所知,在传递参数到作业调度引擎时,WCF Tcp绑定被用作幕后操作。 我想知道如何将自定义对象(可序列化)作为作业参数传递。

谢谢您的建议!

5个回答

51

有两种方法可以传递一个对象,以便在Quartz任务执行时可以检索到:

将实例放入数据映射中。在设置作业时,使用类似这样的键将实例添加到映射中:

// Create job etc...
var MyClass _myInstance;
statusJob.JobDataMap.Put("myKey", _myInstance);
// Schedule job...

可以像这样在作业的Execute()方法中检索实例:

public void Execute(IJobExecutionContext context)
        {
            var dataMap = context.MergedJobDataMap;
            var myInstance = (MyClass)dataMap["myKey"];

或者

当您设置作业时,请像这样将实例添加到调度程序上下文中:

  ISchedulerFactory schedFact = new StdSchedulerFactory();
  _sched = schedFact.GetScheduler();
  _sched.Start();
  // Create job etc...
  var MyClass _myInstance;
  _sched.Context.Put("myKey", myInstance);
  // Schedule job...

要在作业的Execute()方法中检索实例,请执行以下操作:

public void Execute(IJobExecutionContext context)
        {
            var schedulerContext = context.Scheduler.Context;
            var myInstance = (MyClass)schedulerContext.Get("myKey");

当使用JobDataMap时,MyClass实例是如何被序列化的?它需要被标记为[Serializable]吗? - Dejan
Dejan,我没有使用[Serializable],但我的实例可以被检索。据我所知,当您在Quartz中使用持久化JobStore时,才会调用序列化。请注意,Quartz文档警告不要存储非原始类型,如果进行序列化:http://quartz-scheduler.org/documentation/best-practices。基于此,我回答中的示例可能对您没有用处。 - hillstuk
这个效果出奇的好。我能够将MQTTNet客户端实例传递给作业!太棒了! - thinwybk

5
当您安排一个任务时,可以在 JobDetail 对象上设置一个 JobDataMap 并将其传递给您的调度程序,其中有一些限制在 quartz.net教程 中描述。任务可以通过以下方式访问数据:
JobDataMap dataMap = context.JobDetail.JobDataMap;

然而,我更喜欢通过注入到作业中的存储库访问我的工作配置。

谢谢您的回复,但我所寻找的是如何从外部应用程序传递对象。 - Thurein
这也是我需要了解的东西...仍在搜索中。 - evermean
你如何在不使用 JobDataMap 的情况下注入你的仓库?或者你只是注入仓库吗? - David Clarke

5

在多线程环境中,我发现Hillstuk上面的答案无法得到预期的结果。这里是我的解决方案,使用Newtonsoft……享受吧。

public void InitJob() {

    MyClass data = new MyClass {Foo = “Foo fighters”}; 

    /* a unique identifier for demonstration purposes.. Use your own concoction here. */
    int uniqueIdentifier = new Random().Next(int.MinValue, int.MaxValue); 

    IJobDetail newJob = JobBuilder.Create<MyAwesomeJob>()
    .UsingJobData("JobData", JsonConvert.SerializeObject(data))
    .WithIdentity($"job-{uniqueIdentifier}", "main")                
    .Build();

}

/* the execute method */
public class MyAwesomeJob : IJob
{
    public void Execute(IJobExecutionContext context)
    {                   
        var jobData = JsonConvert.DeserializeObject<MyClass>(context.JobDetail.JobDataMap.GetString("JobData"));    
    }
}

/* for completeness */
public class MyClass {
    string Foo { get; set; } 
}

4
您可以将您的实例/对象放在IJobDetail中。
 JobDataMap m = new JobDataMap();
  m.Put("Class1", new Class1(){name="xxx"});


  IJobDetail job = JobBuilder.Create<Job>()
            .WithIdentity("myJob", "group1")
            .UsingJobData(m)//class object
            .UsingJobData("name2", "Hello World!")
            .Build();

使用方法

  public void Execute(IJobExecutionContext context)
        {
 JobDataMap dataMap = context.JobDetail.JobDataMap;
            Class1 class1 = (Class1)dataMap.Get("Class1");
string x = class1.name;
}

0

我是这样传递对象的

JobDetail job1 = JobBuilder.newJob(JobAutomation.class)
                .usingJobData("path", path)
                .withIdentity("job2", "group2").build();

        CronTrigger trigger1 = TriggerBuilder.newTrigger()
                .withIdentity("cronTrigger2", "group2")
                .withSchedule(CronScheduleBuilder.cronSchedule("40 27 11 * * ?"))
                .build();

通过以下代码获取jobdatamap

JobDataMap dataMap = context.getJobDetail().getJobDataMap();
String path =dataMap.getString("path");

1
JobDataMap dataMap = context.getMergedJobDataMap(); 是首选。 - Roger Willcocks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接