Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't Windows Service work properly with System.Timers.Timer or System.Windows.Forms.Timer

I have been recently challenged with writing a Windows Service. I needed to periodically request a URL and check its availability. For this I decided to initialize a timer in OnStart method of the service and do all the work in timer_Tick event.

My first approach was using System.Windows.Forms.Timer and its Tick event. I chose for it, because of the tutorial that I was reading. Somehow I could not make the service work. It installed and started without problems, but it would not fire the event (I attached the debugger to the process and saw that it was not fired). I thought that maybe using Forms timer in Windows service is not a good idea, so I decided to switch to System.Timers.Timer and utilize its Elapsed event. This did not work either. I tried both mentioned approaches in a Windows Forms application and they both worked.

After some digging, I found this site: http://weblogs.asp.net/sibrahim/archive/2004/01/13/58429.aspx on which the blogger advices to utilize yet another timer: System.Threading.Timer. I changed the approach for the third time and BOOM it started working like a charm.

My question is: why can't I use the other timers in Windows services and why is it so difficult to find an information about it?

like image 471
Michal B. Avatar asked Feb 09 '12 09:02

Michal B.


1 Answers

The System.Windows.Forms.Timer timer uses the message pump of the UI to marshal the tick event, a service doesn't run a message pump by default so without a little extra work the System.Windows.Forms.Timer timers will not work.

The System.Timers.Timer is a server-based timer and raises an event on the thread you create it on (I think). If this isn't working, perhaps you aren't starting the timer or the timer runs on a thread that immediately ends (as in, nothing is keeping the thread alive so it finishes).

http://msdn.microsoft.com/en-us/library/system.timers.timer.aspx

The System.Threading.Timer timer uses a callback that runs on a ThreadPool thread and isn't tied to the message pump at all, hence this worked.

When you run Application.Run(myForm) in a WinForms project, that call also runs up the message pump, this manages UI messages. The windows timer you mention is a UI component and expects the message pump to be running in order to cause the tick event to occur on the UI thread.

Take a look here for running a message pump in a Windows Service:

Message pump in .NET Windows service

Further reading:

http://support.microsoft.com/kb/842793

In conclusion, I'd just go with the System.Threading.Timer class.

like image 126
Adam Houldsworth Avatar answered Sep 24 '22 00:09

Adam Houldsworth