伙计们,我正在基于Windows服务.NET实现一个例程,并且正在使用
中的Threading.Timer任务protected override void OnStart(string[] args)
{
base.OnStart(args);
_startupTask = Task.Factory.StartNew(StartupAction, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
}
在我的StartupAction中我正在定义Threading.Timer,如下所示:
private void StartupAction()
{
System.Threading.Timer infamousTimer;
infamousTimer = new System.Threading.Timer(new TimerCallback(runMeEveryHour), null, new TimeSpan(0), new TimeSpan(1, 0, 0));
}
有人会认为这不是一件容易的事情,但由于某种原因,它并不总是有效(在某些PC上运行但在其他PC上运行)。
有谁知道罪魁祸首或环境依赖会是什么?
由于
当Timers超出范围时,不会触发回调。见下面的答案
答案 0 :(得分:3)
您的问题在于您使用Task
并创建完全包含在任务操作中的计时器:
private void StartupAction()
{
System.Threading.Timer infamousTimer;
infamousTimer = new System.Threading.Timer(new TimerCallback(runMeEveryHour), null, new TimeSpan(0), new TimeSpan(1, 0, 0));
}
我认为发生的事情是StartupAction
完成计时器超出范围并被处置/ GC。
而是将计时器变量移到外面:
private Timer infamousTimer;
private void StartupAction()
{
infamousTimer = new System.Threading.Timer(new TimerCallback(runMeEveryHour), null, new TimeSpan(0), new TimeSpan(1, 0, 0));
}
此处的优势还在于OnStop
,您可以干净利落地处理计时器。
当然,为什么要在Task
中做到这一点?在OnStart
中执行此操作时看起来有些过分也会起作用。
我还想指出,如果所有服务都运行一个计时器,那么你最好安排一个计划任务,但我在那里做了一个假设。
请参阅this blog post了解原因。
答案 1 :(得分:1)
当Timers超出范围时,不会触发回调。
答案 2 :(得分:0)
我认为你的StartupAction方法只是结束(事实上它超出了范围并且收集的垃圾是副产品,在我看来)。
您需要修改StartupAction方法以使其保持活动状态。
尝试添加类似:while(true) { Thread.Sleep(1000); }
的内容以保持线程活跃。
private void StartupAction()
{
System.Threading.Timer infamousTimer;
infamousTimer = new System.Threading.Timer(new TimerCallback(runMeEveryHour), null, new TimeSpan(0), new TimeSpan(1, 0, 0));
while(true) { Thread.Sleep(1000); } //this is the simplest logic to keep the thread alive
}