Windows Service to run a function at specified time
Solution 1
(1) On first start, Set _timer.Interval to the amount of milliseconds between the service start and schedule time. This sample set schedule time to 7:00 a.m. as _scheduleTime = DateTime.Today.AddDays(1).AddHours(7);
(2) On Timer_Elapsed, reset _timer.Interval to 24 hours (in milliseconds) if current interval is not 24 hours.
System.Timers.Timer _timer;
DateTime _scheduleTime;
public WinService()
{
InitializeComponent();
_timer = new System.Timers.Timer();
_scheduleTime = DateTime.Today.AddDays(1).AddHours(7); // Schedule to run once a day at 7:00 a.m.
}
protected override void OnStart(string[] args)
{
// For first time, set amount of seconds between current time and schedule time
_timer.Enabled = true;
_timer.Interval = _scheduleTime.Subtract(DateTime.Now).TotalSeconds * 1000;
_timer.Elapsed += new System.Timers.ElapsedEventHandler(Timer_Elapsed);
}
protected void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
// 1. Process Schedule Task
// ----------------------------------
// Add code to Process your task here
// ----------------------------------
// 2. If tick for the first time, reset next run to every 24 hours
if (_timer.Interval != 24 * 60 * 60 * 1000)
{
_timer.Interval = 24 * 60 * 60 * 1000;
}
}
Edit:
Sometimes people want to schedule the service to start at day 0, not tomorrow so they change DateTime.Today.AddDays(0)
.If they do that and set a time in the past it causes an error setting the Interval with a negative number.
//Test if its a time in the past and protect setting _timer.Interval with a negative number which causes an error.
double tillNextInterval = _scheduleTime.Subtract(DateTime.Now).TotalSeconds * 1000;
if (tillNextInterval < 0) tillNextInterval += new TimeSpan(24, 0, 0).TotalSeconds * 1000;
_timer.Interval = tillNextInterval;
Solution 2
Good answer (I used your code), but one problem with this line:
_timer.Interval = _scheduleTime.Subtract(DateTime.Now).TotalSeconds * 1000;
If DateTime.now is later than scheduleTime, you will go negative and this will generate an exception when assigning to timer.Interval.
I used:
if (DateTime.now > scheduleTime)
scheduleTime = scheduleTime.AddHours(24);
Then do the subtraction.
Solution 3
Are you sure, you need a service, that runs only one time per day?
Maybe Windows Task Schedule will be better solution?
Solution 4
Use Windows built in Task Scheduler (http://windows.microsoft.com/en-us/windows7/schedule-a-task) or Quartz.net.
Unless ... you have a service that's doing lots of other processing and needs to be running all the time in which case a Timer might be appropriate.
Related videos on Youtube
Ziyad Ahmad
Updated on April 23, 2021Comments
-
Ziyad Ahmad about 3 years
I wanted to start a Windows service to run a function everyday at specific time.
What method i should consider to implement this? Timer or using threads?
-
Settapon H over 10 yearsInstead of run timer every minutes, this timer will run once a day.
-
RacerNerd over 10 yearsIt looks like you provided a nice code example. It would be helpful to add some explanation of the code around it to specifically address the question from the user.
-
MarceloBarbosa almost 9 yearsInstead of making this a service, if you want it to run at a specific point in time, you could consider making it a normal console application, and running it with the Windows Task Scheduler
-
Mukus over 6 yearsI think if the task takes a long time to execute, it won't run exactly at 7 next time. It will keep growing.
-
Kiquenet about 6 yearsAnd run at
7:00 a.m to 21:00 pm
interval each day Monday To Friday ? Not eastern-holidays -
Kiquenet about 6 yearsany full sample using
Quartz.net
? AppDomain in Windows Service ? Console App? -
C sharper over 5 yearsInstead of the " if (_timer.Interval != 24 * 60 * 60 * 1000) { _timer.Interval = 24 * 60 * 60 * 1000; } " - could be better to do _timer.Interval = (_scheduleTime - DateTime.Now).TotalMilliseconds that's way, it doesn't matter how long the function took, as long as it's less than 24 hours
-
fireshark519 about 5 yearsin that case you should do while (DateTime.now > scheduleTime) { scheduleTime = scheduleTime.AddHours(24); } it just makes it better if it is more than just 1 day....it resolves any weirdness that may happen
-
Shehani Kalapuge over 3 yearsIs this task going to run at 7 am if someone restarts the service in the meantime?