Run Background Task at specific time - Windows 10 App - c#

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/

Related

Thread that executes every X number of days on c# - ASP.NET

Basically what I have to do is create a thread that executes in a given number of days, which can change. The point is that an email should be sent periodically, and I'm looking for the best approach eventhough I know this is definitely not one of the best solutions but I must continue with this per requirements, hence I cannot use Windows Services, Windows Scheduler or anything similar. So the starting day for this email to be sent is when app starts, and then the next time should be after X days as specified in web.config. The problem is that I don't know how to keep track of that if the application stops (I can save the date of application start in database) but the number of days for the next execution may change. This is what I've done so far:
private async Task<int> EmailScheduler()
{
var day = DateTime.Now.Day; //day when app starts
while (true)
{
var currentTime = DateTime.Now;
if (currentTime.Day == day)
{
SendEmail("mailto", "", "", "subject", EmailMessage());
day += Int32.Parse(ConfigurationManager.AppSettings["NumberOfDays"]); //next schedule
}
await Task.Delay((int)TimeSpan.FromDays(1).TotalMilliseconds);
}
}
Thanks in advance.
You have no control over when your application pool restarts, and it will most certainly not be running for extended periods of time.
You could save the last execution date in a database, and periodically poll it to see if it has been longer than your given number of days.
The polling frequency would depend on your requirements.
This would somewhat approach sending a mail "every few days", but it would probably not be as accurate as a scheduled task.

Quartz.net - misfire instructions don't work

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

C#: get next execution time of window service

I am working on a window service and I have to schedule it. Schedule is set to any three days of a week and four times a day. At any time when one starts service, It must pick the next execution time.
This next execution time can be in the same day or next scheduled day(may be with the gap of a day or two).
Take a look at Task Scheduler Managed Library (Codeplex). I believe it is maintained by Microsoft themselves.
Once you add the DLL reference to Microsoft.Win32.TaskScheduler, you can use it really easily like so:
var taskService = new TaskService();
var task = taskService.NewTask();
task.Triggers.Add(new WeeklyTrigger(DaysOfTheWeek.Friday, 1));
task.Actions.Add(new ExecAction("YourProgram.exe", null, null));
task.RootFolder.RegisterTaskDefinition("YourTaskName", task);
That will register a task that runs every Friday, executing YourProgram.exe.

Microsoft.Win32.TaskScheduler RandomDelay

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.

Using System.Timers.Timer in asp.net

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.

Categories