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

C# Threading.Timer not always triggering when in a windows Service Task

伙计们,我正在 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 上无效)。

谁知道罪魁祸首或环境依赖性是什么?

谢谢

当计时器超出范围时,不会触发回调。请参阅下面的答案

您的问题在于您使用 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 完成计时器超出范围并且 disposed/GC'd。

改为将定时器变量移到外面:

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 了解原因。

我认为您的 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
}

当计时器超出范围时,不会触发回调。