C#Threading.Timer并不总是在Windows服务任务中触发

时间:2016-03-22 22:19:52

标签: c# multithreading timer windows-services

伙计们,我正在基于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超出范围时,不会触发回调。见下面的答案

3 个答案:

答案 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
}