I am using quartz.net with CRON scheduling.
I set misfire instruction to : fire and proceed:
trigger = Quartz.TriggerBuilder.Create()
.WithIdentity(jobData.JobId, jobData.ClientApplicationId.ToString())//.WithCronSchedule(scheduleInfo.CronExpression, WithMisfireHandlingInstructionDoNothing())
.WithSchedule(Quartz.CronScheduleBuilder.CronSchedule(new Quartz.CronExpression(scheduleInfo.CronExpression)).WithMisfireHandlingInstructionFireAndProceed())//.WithMisfireHandlingInstructionDoNothing()) ///.WithMisfireHandlingInstructionFireAndProceed()
.StartAt(DateTime.Now).ForJob(iJobDetail)
.Build();
From what I read, if a trigger was missed , it should fire as soon as the scheduler is up
(one time maximum, even if the job was suppose to run many times).
For some reason when I test it, the job is never triggered.
Say I have a job that should run every hour starting from 4:00.
I turn on the scheduler at 7:30 , I don't get any trigger fires - until 8:00.
misfireThreshold is set to (60000) - one minute.
The job is statefuul and does not allow concurrent runs.
I am using a persistent store (AdoJobStore) -saving the schedules to the MSSQL DB.
Any idea why the trigger isn't firing on schedule activation?
Try the code below instead. Make sure to replace {YourCronExpressionString} with your own cron expression.
trigger = Quartz.TriggerBuilder.Create()
.WithIdentity(jobData.JobId, jobData.ClientApplicationId.ToString())
.WithCronSchedule("{YourCronExpressionString}", x => x.WithMisfireHandlingInstructionFireAndProceed())
.StartAt(DateTime.Now).ForJob(iJobDetail)
.Build();
Source: Quartz.NET setting MisfireInstruction
try to use PauseJob(jobKey) method to missfire
use ResumeJob(jobKey) method to trigger it again
for example:
set cronexpression:every 4 hours
at 7:30 , call pauseJob method
and at 8:01,call resumeJob method
the job at 8:00 will be refire
Related
Let's say we have a job and corresponding trigger configured as follows:
var jobKey = new JobKey(typeof(HelloJob).Name, typeof(HelloJob).Name);
IJobDetail job = JobBuilder.Create<HelloJob>()
.WithIdentity(jobKey)
.RequestRecovery()
.Build();
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity(string.Format("{0}Trigger", typeof(HelloJob).Name), typeof(HelloJob).Name)
.StartAt(DateBuilder.FutureDate(1, IntervalUnit.Second))
.WithSimpleSchedule(x => x
.WithIntervalInSeconds(1)
.WithRepeatCount(9))
.Build();
using "quartz.jobStore.type = Quartz.Impl.AdoJobStore.JobStoreTX, Quartz".
Well I expect the job execute 10 times in normal situation and of course it does.
The problem is that I want the job to continue the remaining repeat count if any stop occurres during its life cycle.
For example I stop the program when the fifth execution of the job is done and the next time that I run the program I want to execute the job only five times more but it is executed 10 times.
How should I configure Scheduler, Job and Trigger in order to do this?
You may do this by storing remaining count between program execution:
on program "Stop" save remaining count in external storage (file, db, etc..)
The best way actualy is to do this after each job execution.
on program "Start" read value from storage and use it in .WithRepeatCount() instead of constant.
Make sure the database objects are created and configure jobstores.
Look this example. It can help you.
https://github.com/Leftyx/QuartzNetAdoJobStoreSQLite
I've searched a way to run a Background Task daily at a specific time, e.x. at at 12:00.
I've registered the BackgroundTask with a TimeTrigger, which unfortunately starts immediately after registering.
builder.SetTrigger(new TimeTrigger(24 * 60, false));
Is there a easier way, then checking every hour, if this is the right time of day?
Microsoft seems to avoid apps from triggering at a precise time, but you might be able to get close by calculating the number of minutes from the time the user registers the task to 12:00, then resubscribe another task from there set for 24*60 as you have. I'm unsure if Microsoft allows this within a Background task, but it's worth a shot.
Example of calculating the minutes to midnight for the task
var tommorowMidnight = DateTime.Today.AddDays(1);
var timeTilMidnight = tommorowMidnight - DateTime.Now;
var minutesTilMidnight = (uint)timeTilMidnight.TotalMinutes;
builder.SetTrigger(new TimeTrigger(minutesTilMidnight, true));
I've used this task wrapper to create something like this before and it fired everyday. Maybe this is what you are looking for.
http://taskscheduler.codeplex.com/
When I run a job using Quartz I log the details to a table in my database, and I can see that when I run a job manually, or have scheduled a job, the table gets populated with the job details at the correct time.
However, when I reschedule a job using the built-in RescheduleJob method, the job is fired twice; once when I run the method, and then correctly, at the time the job was rescheduled to.
Example:
Rescheduled Job to 09:01:11, but the job was inserted into the database twice, at:
09:00:23 (seconds after calling RescheduleJob method)
09:01:11 (the rescheduled time)
I've looked through my code and there's nothing calling the job before getting to the RescheduleJob method.
public void RescheduleTrigger(TriggerKey key, string cronexpression)
{
var trigger = this.GetTrigger(key);
var triggerBuilder = trigger.GetTriggerBuilder();
ITrigger newTrigger = triggerBuilder.WithCronSchedule(cronexpression).Build();
this.scheduler.RescheduleJob(trigger.Key, newTrigger);
}
I've Googled around and I've only found one similar case and it was unresolved. Has anyone encountered this before and can help me work around it?
my case in java, have a same situation, but i work around with modifying trigger start time as now
background:
my trigger doesn`t set trigger end time, only set trigger start time, after reschedule, i found out the problem will happen when you reset the time between trigger start time and current system time e.g trigger start time 2016/03/04 10:58 am and current system time 2016/03/04 11:05 am and you set cron expression 0 59 10 * * ?, the next fire time will be set at 2016/03/05 10:59 and fire the job immediately.
After i reset start time before perform "reschedule", problem temporary solved
scheduler.pauseAll();
Date currentDate=new Date();
trigger.setStartTime(currentDate);
scheduler.rescheduleJob(trigger.getName(), trigger.getGroup(), trigger);
scheduler.resumeAll();
Unscheduled the job, and then scheduled it.
this.scheduler.UnscheduleJob(key);
var trigger = this.GetTrigger(key);
var triggerBuilder = trigger.GetTriggerBuilder();
ITrigger newTrigger = triggerBuilder.WithCronSchedule(cronexpression).Build();
this.scheduler.ScheduleJob(newTrigger);
Then went back to using RescheduleJob
var trigger = this.GetTrigger(key);
var triggerBuilder = trigger.GetTriggerBuilder();
ITrigger newTrigger = triggerBuilder.WithCronSchedule(cronexpression).Build();
this.scheduler.RescheduleJob(trigger.Key, newTrigger);
This solved my problem temporarily, but then the issue restarted again.
I have written a little program that creates a scheduled task. I wanted this task to run every day at any time between 6pm and 11.59pm. For this reason, I created this trigger
td.Triggers.Add(new DailyTrigger
{
DaysInterval = 1,
StartBoundary = DateTime.Today + TimeSpan.FromHours(18),
RandomDelay = TimeSpan.FromMinutes(359)
});
Problem is that in the Task Scheduler window the task that I create always is set to run at 6
What am I doing wrong?
This is the correct syntax to achieve your results. Unfortunately, the Task Scheduler app in Windows does not display information about delays. (BTW, I'm the author of that library and am 100% confident that your task will execute as you desire.) For detail on the functionality of the RandomDelay property see the Microsoft documentation.
I use the following code in a asp.net website.
On application init i call InitializeTimer() once.
The goal of the code was to run DoWork() once every hour (1 time per hour) .
I also wanted the code to execute on different time every loop so i added the random part.
The result i got was werid , i can not find a explaination why is happens.
The code executed the function after 2hrs , then again after 2hrs , then after 3hrs , then after 2hrs , and 2hrs again.****
Can anybody explain the reason?
using System.Timers;
....
private static random = new Random();
....
public static void InitializeTimer()
{
tTimer = new Timer();
tTimer.AutoReset = true;
tTimer.Interval = TimeSpan.FromHours(1.0).TotalMilliseconds;
tTimer.Elapsed += new ElapsedEventHandler(ClassName1.tMailer_Elapsed);
tTimer.Start();
}
private static void tTimer_Elapsed(object sender, ElapsedEventArgs e)
{
tTimer.Interval += random.Next(-5, 5);
DoWork();
}
Update:
Please don't post "use windows service" , or "scheduled task".
My question is for the following code I'm not looking for better alternatives.
Also , during this test (10hrs) , website was with high traffic , iis pool did not restart!
Based on the following MSDN: (http://msdn.microsoft.com/en-us/library/system.timers.timer.interval.aspx)
If the interval is set after the Timer
has started, the count is reset. For
example, if you set the interval to 5
seconds and then set the Enabled
property to true, the count starts at
the time Enabled is set. If you reset
the interval to 10 seconds when count
is 3 seconds, the Elapsed event is
raised for the first time 13 seconds
after Enabled was set to true.
Is it possible that re-setting the interval in the elapsed function is the cause of the problem?
Meaning that when tTimer_Elapsed function is called the count is 1hr(min a few millisecond)
and my code "tTimer.Interval += random.Next(-5, 5);" is adding another full hour to the Interval?
ASP.NET applications will get shut down when not in use. If someone hits your site, and then no more hits, it can get shut down. Your timer won't fire.
For this type of maintenance work you want to use a windows scheduled task or windows service.
Check this out... Jeff Atwood actually discussed something similar. I guess it worked, but according to Jeff the site outgrew this method so they went to a dedicated task.
Since .net 4.5.2, there is a class called HostingEnvironment, it can do what you're asking, here is how to use:
https://blog.mariusschulz.com/2014/05/07/scheduling-background-jobs-from-an-asp-net-application-in-net-4-5-2
The HostingEnvironment.QueueBackgroundWorkItem method lets you
schedule small background work items. ASP.NET tracks these items and
prevents IIS from abruptly terminating the worker process until all
background work items have completed.
I second Sams suggestion of using windows scheduled task to hit a page every hour. I tried and tried to get mine to work and it sort of worked. I went to a scheduled task and it has never failed.