问题
We are using Quartz.Net to trigger jobs on a schedule in a Windows Service
.
I have a situation where I have to Trigger a job every 5 minutes
from Start DateTime
till End DateTime
.
After the job is completed we need to calculate the Next Start DateTime
and Next End DateTime
and save to the DB -
For this I tried to override the JobListener
which has a method: JobWasExecuted
public class xPTJobListener : JobListenerSupport
{
public override string Name { get { return "xPTJobListener"; } }
public override void JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException)
{
var dataMap = context.MergedJobDataMap;
var schedule = (MyDTO)dataMap["Schedule"];
using (var logger = new xPTLogger())
{
logger.LogMessage(MessageType.Information, string.Format("Inside JobWasExecuted() - [{0}] - ", schedule.Id));
}
base.JobWasExecuted(context, jobException);
}
}
and also the TriggerComplete
in the TriggerListener
public class xPTTriggerListener : TriggerListenerSupport
{
public override string Name { get { return "xPTTriggerListener"; } }
public override void TriggerComplete(ITrigger trigger, IJobExecutionContext context, SchedulerInstruction triggerInstructionCode)
{
var dataMap = context.MergedJobDataMap;
var schedule = (MyDTO)dataMap["Schedule"];
using (var logger = new xPTLogger())
{
logger.LogMessage(MessageType.Information, string.Format("Inside Trigger Complete - [{0}] - ", schedule.Id));
}
base.TriggerComplete(trigger, context, triggerInstructionCode);
}
}
But the problem with above methods is that they are both executed each time the job is called.
So if I have a Job which runs from 12:01 AM
and ends 12:02 AM
every 5 seconds - Both these methods get called 12 times
What I need is to call a method only once after the One Job iteration has Ended - (After the Job is executed 12 Times)?
How do I do this in Quartz?
EDIT
Creating the Triggers
public static ITrigger GenerateTrigger(RouteMonitorScheduleDTO routeSchedule, double fGmtOffset, xPTLogger logger)
{
ITrigger trigger = null;
switch (routeSchedule.ScheduleInfo.PeriodType)
{
case PeriodTypeEnum.Once:
trigger = TriggerBuilder.Create()
.WithIdentity(string.Format("trigger_{0}", routeSchedule.RouteScheduleId), DefaultGroup)
.StartAt(routeSchedule.DepartureDateTime)
.WithSimpleSchedule(s => s.WithIntervalInMinutes(5))
.EndAt(routeSchedule.ArrivalDateTime.AddMinutes(5))
.Build();
break;
case PeriodTypeEnum.Daily:
case PeriodTypeEnum.WeekDays:
case PeriodTypeEnum.Weekly:
case PeriodTypeEnum.Monthly:
var schedule = routeSchedule.ScheduleInfo;
var cronExpresion = xPTCronBuilder.GenerateCronExpression(
schedule.PeriodType,
schedule.ScheduleStringValue,
fGmtOffset,
routeSchedule.DepartureDateTime,
routeSchedule.ArrivalDateTime.AddMinutes(5), 5);
trigger = TriggerBuilder.Create()
.WithIdentity(string.Format("trigger_{0}", routeSchedule.RouteScheduleId), DefaultGroup)
.WithCronSchedule(cronExpresion)
.Build();
break;
}
return trigger;
}
EDIT Trigger with Cron:
trigger = TriggerBuilder.Create()
.WithIdentity(string.Format("trigger_{0}", 1), "Group1")
.WithCronSchedule("0 0-45/5 7-7 ? * TUE,WED *").Build();
As you can see from above cron expression it will run from 7 AM to 7:45 AM
every 5 minutes
every Tuesday
and Wednesday
.
So 1 iteration is 7AM to 7:45 AM
on Tuesday
, the Next is 7 AM to 7:45
on Wednesday
. I need to call a function after each Iteration has completed.
So let's say that when the Last Trigger is fired for 7:45 AM on Tuesday
- I need to call the function.
回答1:
If I understand your problem correctly, you can do this using ITriggerListener in the following way:
public class xPTTriggerListener : TriggerListenerSupport {
public override string Name
{
get { return "xPTTriggerListener"; }
}
public override void TriggerComplete(ITrigger trigger, IJobExecutionContext context, SchedulerInstruction triggerInstructionCode) {
if (triggerInstructionCode == SchedulerInstruction.DeleteTrigger) {
// means this trigger won't be fired again - now recalculate your dates in database
}
base.TriggerComplete(trigger, context, triggerInstructionCode);
}
}
回答2:
What about creating another job triggered once in a minute for the given period by using the StartTime
or EndTime
as global values?
In addition to this, you could also check the EndTime
value before calling your action method. In this case you execute the action if the current time is equal to or near to DateTime.Now()
or something similar to that:
//...
if(endtime == DateTime.Now())
{
//call your action
}
Hope this helps...
来源:https://stackoverflow.com/questions/36621113/quartz-net-call-a-function-after-the-job-has-completed-full-execution