简体   繁体   中英

C# Timer on Elapsed Time does not call method

The below class is from a .Net Windows Service. The method DoSomeDatabaseStuff takes 10 minutes when it starts the first time but when the time is elapsed this method does not get called again.

public class Test
{
        public void Start()
        {
            DoSomeDatabaseStuff();

            _oTimer = new Timer(60000);
            _oTimer.Elapsed += OnTimeout;
            _oTimer.AutoReset = true;
            _oTimer.Start();
        }

        private void OnTimeout(object source, ElapsedEventArgs e)
        {
            DoSomeDatabaseStuff();

            _oTimer = new Timer(60000);
            _oTimer.Elapsed += OnTimeout;
            _oTimer.AutoReset = true;
            _oTimer.Start();
        }
}

There are lots of serious problems in this code:

  • If the Start method is meant to be the OnStart() method of the service then you can never get the service started. OnStart() must complete in less than 30 seconds. Just initialize the timer and don't do anything else
  • Creating another Timer in the Elapsed event handler is a grave mistake. Your event handler will now run twice. After the second time it is called it will run thrice. Etcetera.
  • Your test program does not test the way the code will run in a service. The Elapsed event handler will never run since the test will have been completed before your event handler can run. Which explains your observation
  • You must use try/catch in the Elapsed event handler. If you don't then any exception will be swallowed without a diagnostic. The System.Timers.Timer class is nasty like that, favor System.Threading.Timer instead Also explains your observation
  • You must ensure that your event handler is re-entrant. It can run again when the previous invocation of the event handler is still busy, this will happen when the task takes more than a minute. This very rarely comes to a good end. Setting AutoReset = false is a simple way to avoid this re-entrancy, start the timer back up at the end of the event handler to get it to repeat.

I use the System.Threading.Timer in windows-services.

Maybe this solves also your issue since others have also problems with the System.Timers.Timer in windows-services: "What I've found is that System.Timers.Timer just doesn't work in my Windows Service application. Therefore I've switched over to System.Threading.Timer "

See: Windows Service System.Timers.Timer not firing

private void InitService()
{
    //starts immediately, interval is in TimeSpan 
    this._oTimer = new System.Threading.Timer(
        OnTimeout,
        null, 
        TimeSpan.Zero,
        TimeSpan.FromMinutes(10)
    );
}

protected override void OnStart(string[] args)
{
    InitService();
}

protected override void OnStop()
{
    this._oTimer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
}

private void ImportTimer_Elapsed(Object state)
{
    DoSomeDatabaseStuff();
}

Your program ends before timer could run. Timer is working in background thread witch is terminated when the main thread stops.

try

static void Main(string[] args)
{
    Test t = new Test();
    t.Start();
    Console.ReadLine();
}

Instead of creating a new timer every time, try setting the OnTimeout handler to:

_oTimer.Stop();
DoSomeDatabaseStuff();
_oTimer.Start();

similarly with the method Start().

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM