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

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 are happening in this class.

SetupTimer methods create a new instance of Timer class specifying intervall how often we want our service should perform some task and the method to call, in this case StartEvent method. In this case method StartEvent will be called each 5th minutes. This method are doing just one thing, calling method Start. This is our kind of entry point where we should implement som business logic. And the reason why we separate Start method from StartEvent is because we want to be able to run our application also from Visual Studio in debug modus. If you remember we are using flag called

Environment.UserInteractive

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 some basic 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.

There is a couple important things everybody has to understand when you deal with Windows Services.

  1. There is a one entry point to the application when you install it as windows service and call start first time.
  2. There is another entry point when you start the service after stop or restart.
  3. And finally we created another entry point to run the application from Visual Studio.

All these entry points can be surprisingly confusing.

In case 1 the flow is like this Main -> StartProgram -> Contstructor to the MyService  -> SetupTimer -> OnStart -> Timer.Start -> after 5 minutes -> StartEvent -> Start

In case 2 the the flow is like this

OnStart -> Timer.Start -> after 5 minutes -> StartEvent -> Start

In case 3 the flow is like this

Main -> StartProgram -> Contstructor to the MyService  -> SetupTimer -> Start.

To create a good exception handling logic we have to cover all these three cases.

The only method we have to modify is Start method in the MyService.cs class and it should looks like this

public void Start()
{
    try
    {
        //Do Something
    }
    catch (Exception exception)
    {
        //logg exception somewhere
    }            
}

In the next blog we are going to take a look at logging and we are going to use Azure Application Insights for this.

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


"Home page" for this blog serie

Timer Class

My public WindowsServiceTemplate repository