Code for executing method every day at specific time C# (Windows Service) failed

吃可爱长大的小学妹 提交于 2019-11-29 04:36:52

GC will collect your timer since you don't have any references to it after OnStart method.

You're just having it as a local variable. I hope you know local variables are eligible for garbage collection once JIT says that they are no longer used in code.

Fix: Just store the timer in a instance variabe, you're done.

private System.Threading.Timer my5AmTimer = null;

protected override void OnStart(string[] args)
{
    //All other code..

   this.my5AmTimer = new System.Threading.Timer(callback, null, next5am - DateTime.Now, TimeSpan.FromHours(24));
}
var timer1 = new System.Threading.Timer(...);

Timers are tricky objects. They are subject to garbage collection, just like any .NET objects, when they are no longer referenced. The syntax of this statement is enough to know when that happens, your usage of var shows that "timer1" is a local variable of a method. In other words, there is no reference left to that Timer object you created after your method returns.

So what exactly keeps a Timer alive and ticking when there is no reference left? You found out: nothing. Whether your timer will actually tick is a crapshoot. If your program keeps running doing other things then it triggers a gen#0 collection and the timer will disappear. It will never tick. If your program doesn't then it will survive long enough to make it to 5am.

You must store the object reference in a variable that ensures it survives long enough. That should be a static variable.

Or use a System.Timers.Timer. It acts a lot like a System.Threading.Timer but has better survival skills. It is guaranteed to stay alive as long as it has an Elapsed event handler and it is enabled.

Please read the fine manual:

Note

As long as you are using a Timer, you must keep a reference to it. As with any managed object, a Timer is subject to garbage collection when there are no references to it. The fact that a Timer is still active does not prevent it from being collected.

Keep a reference to it:

MyService ws = new MyService ();

System.Threading.Timer timer;

protected override void OnStart(string[] args)
{
    ...

    if (timer1 != null)
        timer1.Dispose();

    timer1 = new System.Threading.Timer(callback, null,
        next5am - DateTime.Now, TimeSpan.FromHours(24));
 }

Another option could be telling the GarbageCollector to keep the local variable alive:

GC.KeepAlive(timer1);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!