12

I'm using a System.Timers.Timer and I've got code like the following in my OnStart method in a c# windows service.

timer = new Timer();
timer.Elapsed += timer_Elapsed;
timer.Enabled = true;
timer.Interval = 3600000;
timer.Start();

This causes the code in timer_Elapsed to be executed every hour starting from an hour after I start the service. Is there any way to get it to execute at the point at which I start the service and then every hour subsequently?

The method called by timer_Elapsed takes too long to run to call it directly from OnStart.

Andy
  • 7,646
  • 8
  • 46
  • 69

5 Answers5

20

Just start a threadpool thread to call the worker function, just like Timer does. Like this:

        timer.Elapsed += timer_Elapsed;
        ThreadPool.QueueUserWorkItem((_) => DoWork());
    ...

    void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
        DoWork();
    }

    void DoWork() {
        // etc...
    }
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
2

If you want your Timer to be fired immediately then you could simply just initialize the Timer object without a specified interval (it will default to 100ms which is almost immediately :P), then set the interval within the called function to whatever you like. Here is an example of what I use in my Windows Service:

private static Timer _timer;

protected override void OnStart(string[] args)
{
    _timer = new Timer(); //This will set the default interval
    _timer.AutoReset = false;
    _timer.Elapsed = OnTimer;
    _timer.Start();
}

private void OnTimer(object sender, ElapsedEventArgs args)
{
    //Do some work here
    _timer.Stop();
    _timer.Interval = 3600000; //Set your new interval here
    _timer.Start();
}
John Odom
  • 1,189
  • 2
  • 20
  • 35
2

Use AutoReset Property of System.Timers.Timer and set it value to "true". No need to use timer.Start() because it does the same job as timer.Enabled = true;

timer = new Timer();
timer.Elapsed += timer_Elapsed;
timer.Enabled = true;
timer.Interval = 3600000;
timer.AutoReset = true;

AutoReset = true will set a value indicating that the Timer should raise the Elapsed event each time when the specified interval elapses.

1

Use System.Threading.Timer class instead of System.Timers.Timer as this type is just a wrapper for Threading Timer.

It also suits your requirement.

 System.Threading.Timer timer =
                new System.Threading.Timer(this.DoWork, this, 0, 36000);

Here are the details.

Vijay Sirigiri
  • 4,653
  • 29
  • 31
  • I did that but here at least did not worked. It runs the method just before the time is started but it runs inside the onStart(). – Thiago Jun 28 '12 at 19:25
0

Easy. All you have to do is call your event function manually once.

timer = new Timer();
timer.Elapsed += timer_Elapsed;
timer.Enabled = true;
timer.Interval = 3600000;
timer.Start();
timer_elapsed();

It is, after all, a function. However, if you're actually creating a windows service, and only want it to fire once an hour, this is the wrong way to do it.
You should set up a Windows recurring task. You can configure it to run immediately, and run hourly as well. Make sure you know what you're doing. I've seen it set incorrectly so that it ran hourly but ran twice at the end of the day. See this answer for more info: https://stackoverflow.com/a/4250516/9008140

John Lord
  • 1,941
  • 12
  • 27