2014-09-19 159 views
2

后重新启动INTERVALL我有一个项目,我用TopShelfTopShelf.Quartz如何强制quartz.net作业完成

this example我建设我的工作与

   s.ScheduleQuartzJob(q => 
        q.WithJob(() => JobBuilder.Create<MyJob>().Build()) 
        .AddTrigger(() => TriggerBuilder.Create() 
         .WithSimpleSchedule(builder => builder 
          .WithIntervalInSeconds(5) 
          .RepeatForever()) 
         .Build()) 
       ); 

这触发我的工作即使前一次仍在运行,每五秒钟一次。我真正想做的是开始一项工作,完成后等待五秒钟,然后重新开始。这是可能的还是我必须实现我自己的逻辑(例如通过一个静态变量)。

回答

2

JobListener解决方案是一种强大且灵活的方式,可在完成后重新安排工作。感谢Nate Kerkhofs和stuartd的意见。

在我来说,因为我没有我的工作,不同的情况下,它足以来装饰我的工作类与DisallowConcurrentExecution属性

[DisallowConcurrentExecution] 
public class MyJob : IJob 
{ 
} 

FYI:使用JobListerener与TopShelf.Quartz的代码看起来是这样的

var jobName = "MyJob"; 
var jobKey = new JobKey(jobName); 

s.ScheduleQuartzJob(q => 
      q.WithJob(() => JobBuilder.Create<MyJob>() 
       .WithIdentity(jobKey).Build()) 
      .AddTrigger(() => TriggerBuilder.Create() 
       .WithSimpleSchedule(builder => builder 
        .WithIntervalInSeconds(5) 
       .Build()) 

var listener = new RepeatAfterCompletionJobListener(TimeSpan.FromSeconds(5)); 
var listenerManager = ScheduleJobServiceConfiguratorExtensions 
     .SchedulerFactory().ListenerManager; 
listenerManager.AddJobListener(listener, KeyMatcher<JobKey>.KeyEquals(jobKey)); 

如果您正在使用TopShelf.Quartz.Ninject(像我一样),不要忘了打电话之前UseQuartzNinject()调用ScheduleJobServiceConfiguratorExtensions.SchedulerFactory()

+0

我想提到DisallowConcurrentExecution作为一种可能的解决方案,但你的问题是“*完成后*等待5秒钟,然后重新开始”。 – stuartd 2014-09-23 13:53:34

+0

是的,我的解释有点误导。我的工作可以在零秒和一分钟之间运行(取决于要处理的数据量)。使用'DisallowConcurrentExecution',我的作业每五秒执行一次,或者在执行后立即执行超过五秒钟。在我了解这个属性之前,我认为最好的解决方案是告诉Quartz在工作完成后开始填充,而不是在解雇工作之后开始填充。对于我来说,属性方法已经足够了,但我非常肯定,JobListener方法会派上用场,因为我打算向我的应用程序添加更多作业。 – 2014-09-23 14:15:48

+0

另请注意,您需要从具体类型'JobBuilder.Create '而不是'JobBuilder.Create '创建作业,以便拾取属性。 – fearofawhackplanet 2014-10-15 17:23:10

4

提议@NateKerkhofs会的工作,这样的工作听众:

public class RepeatAfterCompletionJobListener : IJobListener 
{ 
    private readonly TimeSpan interval; 

    public RepeatAfterCompletionJobListener(TimeSpan interval) 
    { 
     this.interval = interval; 
    } 

    public void JobExecutionVetoed(IJobExecutionContext context) 
    { 
    } 

    public void JobToBeExecuted(IJobExecutionContext context) 
    { 
    } 

    public void JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException) 
    { 
     string triggerKey = context.JobDetail.Key.Name + ".trigger"; 

     var trigger = TriggerBuilder.Create() 
       .WithIdentity(triggerKey) 
       .StartAt(new DateTimeOffset(DateTime.UtcNow.Add(interval))) 
       .Build(); 

     context.Scheduler.RescheduleJob(new TriggerKey(triggerKey), trigger); 
    } 

    public string Name 
    { 
     get 
     { 
      return "RepeatAfterCompletionJobListener"; 
     } 
    } 
} 

然后将监听器添加到调度:

var jobKey = "myJobKey"; 
var schedule = new StdSchedulerFactory().GetScheduler(); 
listener = new 
    RepeatAfterCompletionJobListener(TimeSpan.FromSeconds(5)); 

schedule.ListenerManager.AddJobListener 
     (listener, KeyMatcher<JobKey>.KeyEquals(new JobKey(jobKey))); 

var job = JobBuilder.Create(MyJob) 
       .WithIdentity(jobKey) 
       .Build(); 

// Schedule the job to start in 5 seconds to give the service time to initialise 
var trigger = TriggerBuilder.Create() 
       .WithIdentity(CreateTriggerKey(jobKey)) 
       .StartAt(DateTimeOffset.Now.AddSeconds(5)) 
       .Build(); 

schedule.ScheduleJob(job, trigger); 

不幸的是,我不知道如何做到这一点(或者如果它可以完成)与Typshelf.Quartz库使用的流畅语法,我用TopShelf和常规Quartz.Net。

+1

您实际上创建了一个作业侦听器而不是触发器侦听器,因为您从IJobListener继承。我提交了一个编辑。 – Matt 2015-07-05 21:04:12