Reputation: 29
My service will run daily tasks at multiple times. Here is my service code:
private DateTime m_scheduleTime;
private List<Task> m_tasksList; // Task includes id and time ("23:00")
protected override void OnStart(string[] args) {
SetSchedule();
}
private void SetSchedule()
{
Timer[] timers = new Timer[m_tasksList.Count];
int iHours = 0; int iMinutes = 0;
for (int i = 0; i < timers.Length; i++)
{
iHours = Int16.Parse(m_tasksList[i].Time.Split(':')[0]);
iMinutes = Int16.Parse(m_tasksList[i].Time.Split(':')[1]);
m_scheduleTime = DateTime.Today.AddDays(1).AddHours(iHours).AddMinutes(iMinutes);
timers[i] = new Timer();
timers[i].Enabled = true;
timers[i].Interval = m_scheduleTime.Subtract(DateTime.Now).TotalSeconds * 1000;
timers[i].Elapsed += new System.Timers.ElapsedEventHandler(Timer_Elapsed);
}
}
protected void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
DoWork(int taskId);
}
The code above is not tested, I built it from relevant code samples. So my problems are I don't know whether I am on the right track and if I'm right, I don't know which timer fires the _Elapsed event so that I can pass respective parameter. Any better solution would be appreciated!
Upvotes: 1
Views: 3071
Reputation: 1875
You'd likely have better results using a single System.Threading.Timer
that expires periodically at some minimum resolution, say every 60 seconds.
When your service starts, calculate the next scheduled run time for all of your tasks, inserting them into a priority queue as you go. The priority queue should be ordered by the scheduled run time.
Each time your timer expires, evaluate the scheduled run time of the task at the head of your queue. If the task's run time has been reached, pop it from the queue and push it to queue where it will be executed by your worker threads. Repeat this process until you either run out of tasks in the queue or find a task that is not yet ready to run.
Once a task has completed, calculate it's next scheduled run time and insert it into the scheduled priority queue.
If your service is purely for the purpose of running these scheduled tasks, I would suggest that you consider using the Windows Task Scheduler instead. Honestly, even if your service provides other functionality, using the Windows Task Scheduler to run periodic tasks will still be a better option than trying to roll your own scheduler.
You can find a managed wrapper for the Windows Task Scheduler, here http://taskscheduler.codeplex.com/. I have no knowledge of this wrapper, I found it referenced in this question: C# API for Task Scheduler 2.0.
Upvotes: 2