Here is the link to the "home page" for this blog serie.

Next step is to add scheduling. Normally you implement windows service because you want to perform some task multiple times, for example each five minutes or once a day.

We utilize a Timer class and move the MyService class to separate file.

Now the structure looks like this

Solution Explorer

And MyService.cs looks like this

using System.ServiceProcess;
using System.Timers;

namespace WindowsServiceTemplate
{
    public class MyService : ServiceBase
    {
        public Timer Timer { get;protected set; }

        public MyService()
        {
            SetupTimer();
        }
        protected override void OnStart(string[] args)
        {
            Timer.Start();
        }
        protected override void OnStop()
        {
            Timer.Stop();
        }

        private void SetupTimer()
        {
            Timer = new Timer()
            {
                //300 ms or 5 minutes
                Interval = 300               
            };
            Timer.Elapsed += StartEvent;            
        }
        private void StartEvent(object sender, ElapsedEventArgs e)
        {
            Start();
        }

        public void Start()
        {
            //Do Something
        }
    }
}

A couple of interesting things happens in this class.

SetupTimer methods create a new instance of Timer class and we specifying intervall how often we want our service should perform some task and the method to call.

We also override OnStart and OnStop methods from ServiceBase class where we just starting our Timer and stopping it.

So when we start our windows service the Timer starts and when five minutes is gone StartEvent is called.  

Now it's time to set up exceptions handling. There are two main rules when it comes to exceptions handling, actually three

  1. Try/catch exceptions on the top most level (like main method or other entry points level)
  2. Try/catch exceptions on the lowest level where you expect something can go wrong
  3. Don't polute your code with try/catch everywhere

Keep this in mind always start with handling exceptions on the top most level, this is also easiest. Take a look at the program.cs class after refactoring

using System;
using System.ServiceProcess;

namespace WindowsServiceTemplate
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                StartProgram();
            }
            catch(Exception exception)
            {
               // LogSomewhere();
            } 
        }

        private static void StartProgram()
        {
            if (Environment.UserInteractive)
            {
                using (var service = new MyService())
                {
                    service.Start();
                    Console.WriteLine("Running, press any key to stop");
                    Console.ReadKey();
                }
            }
            else
            {
                ServiceBase.Run(new MyService());
            }
        }
    }
}


We just moved all functionality to the StartProgram method and call it inside try/catch block.

Another best practice is to catch all exception f.ex. IOException or FileLoadException or many others, you expect to get or getting when you are developing.

Here is the link to the "home page" for this blog serie.


"Home page" for this blog serie

Timer Class