0

What I want, a windows service that performs a function with a interval, without opening multiple threads.

What I did, using a Threading.Timer I created the following code:

protected override void OnStart(string[] args) {
  System.Threading.Timer timer1 = new System.Threading.Timer(new TimerCallback(Risk), null, 60000, Timeout.Infinite);
}
public void Risk(object state) {
  try{
    //long operation
  }
  catch(ex){
  }
  finally{
    timer1.Change(1000, Timeout.Infinite);
  }
}

My problem, it looks like this code is opening multiple threads. Is this possible? Where did I go wrong? This a good way to get what I want?

UPDATE (using System.Timers.Timer):

 protected override void OnStart(string[] args) {
    System.Timers.Timer aTimer;
    aTimer = new System.Timers.Timer(60000);
    aTimer.Elapsed += Risk;
    aTimer.AutoReset = true;
    aTimer.Enabled = true;
 }

 private void Risk(Object source, ElapsedEventArgs e) {
    aTimer.Enabled = false;
    try{}
    catch(ex){}
    finally{
      aTimer.Interval = 1000;
      aTimer.Enabled = true;
    }
 }
  • Please read the documentation on System.Threading.Timer in MSDN. It clearly states that the callback method must be reentrant and can be called multiple times simultaneously. – PMF Oct 08 '18 at 14:14
  • Have a look in here: https://stackoverflow.com/questions/27189750/best-way-to-do-a-task-looping-in-windows-service Or some of the other answers here: https://stackoverflow.com/questions/503564/how-might-i-schedule-a-c-sharp-windows-service-to-perform-a-task-daily – gooleem Oct 08 '18 at 14:23
  • To fix: At the start of the timer callback disable the time, then reenable it at the end of the callback. – Matthew Watson Oct 08 '18 at 14:25
  • why not an infinite for with thread.sleep ? – Muds Oct 08 '18 at 16:15
  • @MatthewWatson that's not enough because multiple ticks can be enqueued or execute the same line at the same time. – usr Oct 08 '18 at 16:47
  • Thanks everyone, I've taken a look at the documentation, and like PMF says my problem is my callback method should be reentrant. I change to System.Timers.Timer, and i disable the timer like Matthew suggested. But i still have doubts if only that resolve the problem. I update the code. – Raul Pires Oct 08 '18 at 17:08

1 Answers1

1

Multiple timer ticks can run concurrently. The timer class does not wait for ticks to complete. (I think it should have such a feature because it's almost always what you want.)

An easy fix is to run an loop with Task.Delay:

while (!cancel) {
 DoStuff();
 await Task.Delay(...);
}

And you kick that off with Task.Run(() => { AsyncCodeHere(); });.

usr
  • 168,620
  • 35
  • 240
  • 369
  • 1
    So, my code will look like the one posted by gooleem: https://stackoverflow.com/questions/27189750/best-way-to-do-a-task-looping-in-windows-service Thanks i will work in that... – Raul Pires Oct 08 '18 at 17:30