5

这是我的石英配置:

  <quartz>
    <add key="quartz.scheduler.instanceName" value="EmailScheduler" />
    <!-- Configure Thread Pool -->
    <add key="quartz.threadPool.type" value="Quartz.Simpl.SimpleThreadPool, Quartz" />
    <add key="quartz.threadPool.threadCount" value="10" />
    <add key="quartz.threadPool.threadPriority" value="Normal" />
    <!-- Configure Job Store -->
    <add key="quartz.jobStore.misfireThreshold" value="60000" />
    <add key="quartz.jobStore.type" value="Quartz.Impl.AdoJobStore.JobStoreTX, Quartz" />
    <add key="quartz.jobStore.driverDelegateType" value="Quartz.Impl.AdoJobStore.StdAdoDelegate, Quartz" />
    <add key="quartz.jobStore.dataSource" value="default" />
    <add key="quartz.jobStore.lockHandler.type" value="Quartz.Impl.AdoJobStore.UpdateLockRowSemaphore, Quartz" />
    <add key="quartz.dataSource.default.provider" value="SqlServer-20" />
    <add key="quartz.dataSource.default.connectionString" value="data source= ......" />
    <add key="quartz.jobStore.tablePrefix" value="QRTZ_" />
  </quartz>

这是我的IInterruptableJob

public class JobC : Quartz.IInterruptableJob
{
    public void Interrupt()
    {
        Console.WriteLine("Job Interrupt() called at " + DateTime.Now);
    }

    public void Execute(IJobExecutionContext context)
    {
        // what code I should write here to detect misfires???
        Console.WriteLine("FireTime at " + context.FireTimeUtc.Value + " PreviousFireTime at:" + (context.PreviousFireTimeUtc.HasValue ? context.PreviousFireTimeUtc.Value.ToString() : "NULL"));
    }
}

这是我的工作和触发器:

var job = JobBuilder.Create<JobC>().WithIdentity(new JobKey("JobC")).RequestRecovery(true).Build();
var trigger = TriggerBuilder.Create()
    .WithSimpleSchedule(x => x
        .RepeatForever()
        .WithIntervalInSeconds(2)
            // I'm ignoring misfires here, but seems it doesn't work!
        .WithMisfireHandlingInstructionIgnoreMisfires())
    .StartNow()
    .Build();

var scheduler = new Quartz.Impl.StdSchedulerFactory().GetScheduler();
scheduler.Start();
scheduler.ScheduleJob(job, trigger);

在我调用scheduler.PauseAll()所有工作暂停并调用scheduler.ResumeAll()所有未命中的火灾之后,被解雇!但我想忽略它们,从现在开始继续。

提前致谢。

4

3 回答 3

3

您确定您的触发器满足定义的失火阈值吗?如果您在配置状态时有 60 秒的阈值,则每个未被视为未触发但已达到其预定触发时间的触发器将在恢复后尽快触发。

因此,如果您的暂停持续为最小阈值(在本例中为 60 秒),您应该会看到忽略行为。

于 2012-11-07T16:07:21.890 回答
3

这可能看起来很愚蠢,但我做了以下扩展方法来检测Execute方法内部的失火:

public static bool IsMissedFire(this IJobExecutionContext context, int offsetMilliseconds)
{
    if (!context.ScheduledFireTimeUtc.HasValue)
        return false;
    if (!context.FireTimeUtc.HasValue)
        return false;

    var scheduledFireTimeUtc = context.ScheduledFireTimeUtc.Value;
    var fireTimeUtc = context.FireTimeUtc.Value;

    return fireTimeUtc.Subtract(scheduledFireTimeUtc).TotalMilliseconds > offsetMilliseconds;
}

用法很简单:

public void Execute(IJobExecutionContext context)
{
    if (context.IsMissedFire(1000))
        Console.WriteLine("Missfire");
    else
        Console.WriteLine("Fire");
}
于 2012-11-09T13:55:13.377 回答
2

虽然它适用于 Quartz 的 Java 版本,但下面的链接很好地概述了不同的失火策略:

http://nurkiewicz.blogspot.co.uk/2012/04/quartz-scheduler-misfire-instructions.html

本质上,WithMisfireHandlingInstructionIgnoreMisfires 实际上会在线程可用时立即执行失火,这似乎非常违反直觉。为了丢弃所有失火并继续您需要使用 withMisfireHandlingInstructionNextWithRemainingCount 的计划。

于 2012-11-20T15:02:40.510 回答