Windows Service with Timer

Best Timer for using in a Windows service

Both System.Timers.Timer and System.Threading.Timer will work for services.

The timers you want to avoid are System.Web.UI.Timer and System.Windows.Forms.Timer, which are respectively for ASP applications and WinForms. Using those will cause the service to load an additional assembly which is not really needed for the type of application you are building.

Use System.Timers.Timer like the following example (also, make sure that you use a class level variable to prevent garbage collection, as stated in Tim Robinson's answer):

using System;
using System.Timers;

public class Timer1
{
private static System.Timers.Timer aTimer;

public static void Main()
{
// Normally, the timer is declared at the class level,
// so that it stays in scope as long as it is needed.
// If the timer is declared in a long-running method,
// KeepAlive must be used to prevent the JIT compiler
// from allowing aggressive garbage collection to occur
// before the method ends. (See end of method.)
//System.Timers.Timer aTimer;

// Create a timer with a ten second interval.
aTimer = new System.Timers.Timer(10000);

// Hook up the Elapsed event for the timer.
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);

// Set the Interval to 2 seconds (2000 milliseconds).
aTimer.Interval = 2000;
aTimer.Enabled = true;

Console.WriteLine("Press the Enter key to exit the program.");
Console.ReadLine();

// If the timer is declared in a long-running method, use
// KeepAlive to prevent garbage collection from occurring
// before the method ends.
//GC.KeepAlive(aTimer);
}

// Specify what you want to happen when the Elapsed event is
// raised.
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
}
}

/* This code example produces output similar to the following:

Press the Enter key to exit the program.
The Elapsed event was raised at 5/20/2007 8:42:27 PM
The Elapsed event was raised at 5/20/2007 8:42:29 PM
The Elapsed event was raised at 5/20/2007 8:42:31 PM
...
*/

If you choose System.Threading.Timer, you can use as follows:

using System;
using System.Threading;

class TimerExample
{
static void Main()
{
AutoResetEvent autoEvent = new AutoResetEvent(false);
StatusChecker statusChecker = new StatusChecker(10);

// Create the delegate that invokes methods for the timer.
TimerCallback timerDelegate =
new TimerCallback(statusChecker.CheckStatus);

// Create a timer that signals the delegate to invoke
// CheckStatus after one second, and every 1/4 second
// thereafter.
Console.WriteLine("{0} Creating timer.\n",
DateTime.Now.ToString("h:mm:ss.fff"));
Timer stateTimer =
new Timer(timerDelegate, autoEvent, 1000, 250);

// When autoEvent signals, change the period to every
// 1/2 second.
autoEvent.WaitOne(5000, false);
stateTimer.Change(0, 500);
Console.WriteLine("\nChanging period.\n");

// When autoEvent signals the second time, dispose of
// the timer.
autoEvent.WaitOne(5000, false);
stateTimer.Dispose();
Console.WriteLine("\nDestroying timer.");
}
}

class StatusChecker
{
int invokeCount, maxCount;

public StatusChecker(int count)
{
invokeCount = 0;
maxCount = count;
}

// This method is called by the timer delegate.
public void CheckStatus(Object stateInfo)
{
AutoResetEvent autoEvent = (AutoResetEvent)stateInfo;
Console.WriteLine("{0} Checking status {1,2}.",
DateTime.Now.ToString("h:mm:ss.fff"),
(++invokeCount).ToString());

if(invokeCount == maxCount)
{
// Reset the counter and signal Main.
invokeCount = 0;
autoEvent.Set();
}
}
}

Both examples comes from the MSDN pages.

Windows service with timer

First approach with Windows Service is not easy..

A long time ago, I wrote a C# service.

This is the logic of the Service class (tested, works fine):

namespace MyServiceApp
{
public class MyService : ServiceBase
{
private System.Timers.Timer timer;

protected override void OnStart(string[] args)
{
this.timer = new System.Timers.Timer(30000D); // 30000 milliseconds = 30 seconds
this.timer.AutoReset = true;
this.timer.Elapsed += new System.Timers.ElapsedEventHandler(this.timer_Elapsed);
this.timer.Start();
}

protected override void OnStop()
{
this.timer.Stop();
this.timer = null;
}

private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
MyServiceApp.ServiceWork.Main(); // my separate static method for do work
}

public MyService()
{
this.ServiceName = "MyService";
}

// service entry point
static void Main()
{
System.ServiceProcess.ServiceBase.Run(new MyService());
}
}
}

I recommend you write your real service work in a separate static method (why not, in a console application...just add reference to it), to simplify debugging and clean service code.

Make sure the interval is enough, and write in log ONLY in OnStart and OnStop overrides.

Hope this helps!

How to start method on timer from windows service?

You should use System.Threading.Timer instead of System.Timers.Timer.

Here is the reference for this:

https://msdn.microsoft.com/en-us/library/system.threading.timer(v=vs.110).aspx

Also, another thread about the same topic:

System.Timers.Timer vs System.Threading.Timer

You should lock the execution, avoiding the second execution before the first one finishes.

Running timer immediately in a windows service

Presuming you left nothing out of your example, your timer elapsed method will run on the ThreadPool.

So I would change this line in OnStart

DO();

...with this line:

ThreadPool.QueueUserWorkItem(x => Do());

It has the same net effect of what would happen if the timer fired immediately and, more importantly, will not block on that line.

windows service (with timer) not working without console

When you run / debug your code in Visual Studio then Environment.UserInteractive is true and the process stops right away. This behaviour is by design and you should not do something to make it wait (e.g. call Console.ReadLine()).

You need to run your code as a Windows service (instead of a console application) and then it will be managed by the Services Control Manager. This means that you can configure it to start automatically at system startup and to keep running. You can also start and stop it via the Services Snap-In in the Windows Management Console (services.msc). But for this to work you first need to install your service.

Follow these steps:

  1. Create a new 'Windows Service' project. You will notice that the output type is already set to 'Windows Application'.
  2. Paste your code into the new Program.cs file and remove the Console.ReadLine() statement
  3. Add an installer
  4. Install the service
  5. Run services.msc. You should find a service called 'Service1'. Right-click on it to start it.
  6. Go to the event log and you will find an entry every 2 seconds

References:

  • Introduction to Windows Service Applications
  • How to: Create Windows Services

C# Windows Service, Timer won't tick

Error in VS - You added timerSystemTimer but did not remove timerMainTick component which still references timerMainTick_Tick as handler of it's Tick event. Compiler does not find this handler method anymore since you changed it to timerSystemTimer_Tick.

Adding different timer - Never modify designer file code. You could add a System.Timers.Timer instance to your class code, instantiate it in OnStart and provide handler for Elapsed event. Here's a sample for you.

Run timer in windows service

You declare the member

private aTimer timer;

but you never actually call the constructor, like:

timer = new aTimer();

So in your WindowsService.StartTimer() method you get a NullReferenceException. Add the above line to your service's constructor and you should be fine.

Use of Timer in Windows Service

Firstly, pick the right kind of timer. You want either System.Timers.Timer or System.Threading.Timer - don't use one associated with a UI framework (e.g. System.Windows.Forms.Timer or DispatcherTimer).

Timers are generally simple

  1. set the tick interval
  2. Add a handler to the Elapsed event (or pass it a callback on construction),
  3. Start the timer if necessary (different classes work differently)

and all will be well.

Samples:

// System.Threading.Timer sample
using System;
using System.Threading;

class Test
{
static void Main()
{
TimerCallback callback = PerformTimerOperation;
Timer timer = new Timer(callback);
timer.Change(TimeSpan.Zero, TimeSpan.FromSeconds(1));
// Let the timer run for 10 seconds before the main
// thread exits and the process terminates
Thread.Sleep(10000);
}

static void PerformTimerOperation(object state)
{
Console.WriteLine("Timer ticked...");
}
}

// System.Timers.Timer example
using System;
using System.Threading;
using System.Timers;
// Disambiguate the meaning of "Timer"
using Timer = System.Timers.Timer;

class Test
{
static void Main()
{
Timer timer = new Timer();
timer.Elapsed += PerformTimerOperation;
timer.Interval = TimeSpan.FromSeconds(1).TotalMilliseconds;
timer.Start();
// Let the timer run for 10 seconds before the main
// thread exits and the process terminates
Thread.Sleep(10000);
}

static void PerformTimerOperation(object sender,
ElapsedEventArgs e)
{
Console.WriteLine("Timer ticked...");
}
}

I have a bit more information on this page, although I haven't updated that for a long time.



Related Topics



Leave a reply



Submit