Philippsen's Blog

Everyday findings in my world of .net and related stuff

Execute job within a Windows Service at a certain time

Posted by Torben M. Philippsen on October 28, 2010

Quite often I am asked to create a job to run within a windows service – the following demands applies:

  • A Windows Service is needed since the demands for applying a schedule is not met by the “Scheduled Tasks” features from Windows. Due to that a Console App is ruled out.
  • The job routine must be executed at a certain time – this must be configurable.
  • When the job routine has been executed a schedule must be started – this must be configurable.

To accomplish this we will use:

  • an app.config file to hold our configuration
  • Two Timers – remember to use System.Threading.Timer rather than the System.Windows.Forms.Timer

What we need to do is:

  • Create an OnStart event that starts the processing in a separate thread. This is always a good idea since you will avoid start problems if the process your are starting takes some time to finish.
  • Calculate the time from now and until the job is supposed to run. Start a timer with exactly that delay by setting the duetime of the Timer.
  • When the job executes… Create a new timer and set the Period of the Timer to correspond to the wanted schedule.

Here’s an example of one way to accomplish the task:

    1         protected override void OnStart(string[] args)

    2         {

    3             //Start the actual job in a separate thread to avoid timeouts on start

    4             backgroundWorker = new System.ComponentModel.BackgroundWorker();

    5             backgroundWorker.WorkerReportsProgress = false;

    6             backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);

    7             backgroundWorker.RunWorkerAsync();

    8         }

    9

   10         void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)

   11         {

   22             //the timer that initilizes that the job is executed for the first time at a certain time

   12             StartInitTimer();

   13         }

Let’s look at the StartInitTimer() method:

   30         ///<summary>

   31         /// Starts the initializing timer. this timer runs once and sets the aplicationlogic to run on the configured schedule

   32         ///</summary>

   33         private void StartInitTimer()

   34         {

   35             //calcuale the delay until the point of starting time

   36             DateTime start = DateTime.Parse(ConfigurationManager.AppSettings[“ImportStartTime”]);

   37             DateTime current = DateTime.Now;

   38             TimeSpan timeBeforeStart;

   39             if (start < current)

   40             {

   41                 //the starttime for today has passed – calculate the start time after midnight

   42                 DateTime midnight = GetMidnight();

   43                 TimeSpan timeBeforeMidnight = midnight.Subtract(current);

   44                 timeBeforeStart = timeBeforeMidnight.Add(new TimeSpan(start.Hour, start.Minute, start.Second));

   45             }

   46             else

   47             {

   48                 timeBeforeStart = start.Subtract(current);

   49             }

   50             //start the timer

   51             initTimer = new System.Threading.Timer(InitTimer_Elapsed, null, timeBeforeStart, new TimeSpan(0, 0, 0)); //setting timespan to -1 milliseconds causes the timer to run once

   52         }

   53

   54         ///<summary>

   55         /// Helper method – Calculates a datetime object for the next coming midnight

   56         ///</summary>

   57         ///<returns></returns>

   58         private DateTime GetMidnight()

   59         {

   60             DateTime midnight = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 0, 0, 0);

   61             midnight = midnight.AddDays(1);

   62             return midnight;

   63         }

   64

   65         ///<summary>

   66         /// handles the elapsed event of the imitializing timer

   67         ///</summary>

   68         ///<param name=”sender”></param>

   69         ///<param name=”e”></param>

   70        private void InitTimer_Elapsed(object state)

   71         {

   72             //import is executed one time only in this eventhandler.

   73             try

   74             {

   75                 //Start the schedule

   76                 StartScheduleTimer();

   77                 //perform the job

   78                 DoSomething();

   79

   80             }

   81             catch (Exception ex)

   82             {

   83

   84             }

   85             finally

   86             {

   87                 //dispose the timer object – this timer has done it’s purpose

   88                 initTimer.Dispose();

   89             }

   90

   91         }

  100         private void StartScheduleTimer()

  101         {

  102             //the interval in hours

  103             //                                                                                   s     m    h

  104             int timerInterval = int.Parse(ConfigurationManager.AppSettings[“TimerInterval”]) * 1000 * 60 * 60;

  105             scheduleTimer = new System.Threading.Timer(ScheduleTimer_Elapsed, null, timerInterval, System.Threading.Timeout.Infinite);

  106         }

  107

  108

  109         ///<summary>

  110         /// Every time the timer ticks – the ScheduleTimer_Elapsed method is triggered – the job stuff is being performed here

  111         ///</summary>

  112         ///<param name=”sender”></param>

  113         ///<param name=”e”></param>

  114         private void ScheduleTimer_Elapsed(object state)

  115         {

  116             //reset the timer – set the due/wait time until next event firing

  117             //                                                                                  s     m    h

  118             scheduleTimer.Change(int.Parse(ConfigurationManager.AppSettings[“TimerInterval”]) * 1000 * 60 * 60, System.Threading.Timeout.Infinite);

  119             //perform the job

  120             DoSomething();

  121         }

Advertisements

7 Responses to “Execute job within a Windows Service at a certain time”

  1. Time Me said

    Can you post a link to a fully-working project in a .zip or .rar? I was trying to implement what you have in my own service and it looks like a couple of inferred parts are missing.

    Thanks.

  2. Juan said

    Hi philippsen,
    I truly enjoy this piece of work, not only save my day but is smart and the presentation is very clear with requirements and the explanation, all blogs should follow this model.

    I would like to translate your work to Spanish and post in my blog with all your credits, please let me know if you are ok with this. Thanks in advance, Juan.

    • philippsen said

      Hi Juan!

      Thank you very much for the nice feedback. I’m glad to hear You like my work and that it helped you out.
      Please feel free to translate the post and use it in any way – the more the merrier.
      I would be happy to receive some credits in your post.

      Regards,
      Torben Philippsen

  3. Yasin said

    Can you please e-mail the code-snap. It is not avilable.

  4. Gijs said

    Hi philippsen, can you upload the ZIP-file with your code onze more? the original download stopped working..

    Thx!

Sorry, the comment form is closed at this time.

 
%d bloggers like this: