Best Timer For Using in a Windows Service

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.

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.

Which one is better to use in windows service, Thread or Timer?

Based on your comment that your goal is to run some code at specific intervals:

Conceptually it is better to use a timer than to make your thread sleep. This is what timers are made for. If you choose the thread sleep approach instead I think that in practice it will work fine anyways, although the better practice is to use timers.

There is a third approach - using a job scheduler. You can use windows task scheduler or the more powerful quartz.net (nuget package here).


This is really a question about how you value semantic correctness to pragmatism.

  • From a semantic correctness perspective the best approach is to use a job scheduler since you actually want to schedule a job.
  • From a pragmatic perspective the best approach is probably to just continue using the service you already developed even though it makes the thread sleep, and spend your time on something else than modifying your fully working code.

More opinions about timer vs. job scheduler: Best Timer for using in a Windows service

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.

Using a timer in a long running windows service

You timer is local to the OnStart method. It should not be. It should be a field of your service class, so you don't need to cheat the garbage collector using hints.

Edit:
You did not specify your usings. Make sure by using Timer you are using System.Timers.Timer, not the System.Windows.Forms.Timer.

Best use of Windows Service for repeating a program call

Here's a template you can use it handles the reentrantcy problems with using a timer.

public partial class Service : ServiceBase{

System.Timers.Timer timer;


public Service()
{

timer = new System.Timers.Timer();
//When autoreset is True there are reentrancy problme
timer.AutoReset = false;


timer.Elapsed += new System.Timers.ElapsedEventHandler(DoStuff);
}

protected override void OnStart(string[] args)
{

timer.Interval = 1;
timer.Start();

}

private void DoStuff(object sender, System.Timers.ElapsedEventArgs e)
{

Collection stuff = GetData();
LastChecked = DateTime.Now;

foreach (Object item in stuff)
{
item.Dosomthing(); //Do somthing should only be called once
}


TimeSpan ts = DateTime.Now.Subtract(LastChecked);
TimeSpan MaxWaitTime = TimeSpan.FromMinutes(5);


if (MaxWaitTime.Subtract(ts).CompareTo(TimeSpan.Zero) > -1)
timer.Interval = MaxWaitTime.Subtract(ts).Milliseconds;
else
timer.Interval = 1;

timer.Start();





}

OnContinue OnPause and OnStop are petty easy to work out.

    protected override void OnPause()
{

base.OnPause();
this.timer.Stop();



}

protected override void OnContinue()
{
base.OnContinue();
this.timer.Interval = 1;
this.timer.Start();

}

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

C# Windows Service timer ticks more than one

Assuming you're using System.Timers.Timer then Timer events are raised in a background thread usually which means without any locking your timer event methods can overlap.

An easy solution is to set AutoReset to false and instead in your timer event restart it once complete, for example:

private bool terminating;

public Service()
{
terminating = false;

timer = new Timer(1000);
timer.Elapsed += new ElapsedEventHandler(runProcess);
timer.Enabled = true;
timer.AutoReset = false;
}

protected override void OnStart(string[] args)
{
timer.Start();
}

protected override void OnStop()
{
terminating = true;
timer1.Stop();
}

private void runProcess(object sender, ElapsedEventArgs e)
{
// Do stuff

if (!terminating)
timer.Start(); // Restart timer
}


Related Topics



Leave a reply



Submit