带有计时器的.NET Windows服务停止响应

我有一个用c#编写的Windows服务。 它内部有一个计时器,可以定期激活一些function。 所以我服务的骨架:

public partial class ArchiveService : ServiceBase { Timer tickTack; int interval = 10; ... protected override void OnStart(string[] args) { tickTack = new Timer(1000 * interval); tickTack.Elapsed += new ElapsedEventHandler(tickTack_Elapsed); tickTack.Start(); } protected override void OnStop() { tickTack.Stop(); } private void tickTack_Elapsed(object sender, ElapsedEventArgs e) { ... } } 

它工作了一段时间(如10-15天)然后停止。 我的意思是服务显示为正在运行,但它没有做任何事情。 我做了一些日志记录,问题可能是计时器,因为在间隔之后它不会调用tickTack_Elapsed函数。

我正在考虑在没有计时器的情况下使用无限循环重写它,这会在我设置的时间内停止处理。 这也不是一个优雅的解决方案,我认为它可能会对内存产生一些副作用。

Timer是从System.Timers命名空间使用的,环境是Windows 2003.我在不同服务器上的两个不同服务中使用了这种方法,但两者都产生了这种行为(这就是为什么我认为它以某种方式连接到我的代码或框架本身)。

有人经历过这种行为吗? 有什么不对?


编辑:

我编辑了这两项服务。 到处都有一个很好的尝试捕获和更多的日志记录。 第二个定期进行定时娱乐。 他们都没有因为他们而停止,所以如果这种情况再持续一周,我将关闭这个问题。 到目前为止,感谢大家。


编辑:

我关闭了这个问题因为什么都没发生 我的意思是我做了一些更改,但这些更改在这个问题上并不真正相关,而且从那时起两个服务都没有任何问题。 请将其标记为“已关闭且不再相关”。

像许多受访者一样指出exception被计时器吞噬。 在我的Windows服务中,我使用System.Threading.Timer。 它有Change(…)方法,允许您启动/停止该计时器。 exception的可能位置可能是重入问题 – 如果tickTack_Elapsed执行的时间长于计时器周期。 通常我会像这样编写定时器循环:

  void TimeLoop(object arg) { stopTimer(); //Do some stuff startTimer(); } 

您还可以lock(...)主循环以防止重入。

吞噬了计时器中未处理的exception,他们默默地杀死计时器

将计时器代码的主体包装在try-catch块中

我之前已经看过这个定时器和循环服务。 通常情况是捕获的exception会停止计时器或循环线程,但不会在exception恢复过程中重新启动它。

对于你的其他要点…我不认为有关于计时器的任何“优雅”。 对我来说,在代码中看到循环操作比定时器方法更直接。 但优雅是主观的。

记忆问题? 如果你写的不正确。 如果您的Thread.Sleep()设置不正确,可能会造成处理器负担。

http://support.microsoft.com/kb/842793

这是一个已知的错误,不止一次在框架中重新出现。

最着名的解决方法是:不要使用计时器。 我通过做一个愚蠢的“while(true)”循环来使这个bug无效。

您的里程可能会有所不同,因此请使用您的OS / Framework位组合进行validation。

有趣的问题。 如果它真的只是时间相关(即不是例外),那么我想知道你是否可以简单地定期回收计时器 – 即

 private void tickTack_Elapsed(object sender, ElapsedEventArgs e) { CheckForRecycle(); // ... actual code } private void CheckForRecycle() { lock(someLock) { if(++tickCount > MAX_TICKS) { tickCount = 0; tickTack.Stop(); // re-create timer tickTack = new Timer(...); tickTack.Elapsed += ... tickTack.Start(); } } } 

您可以将其中的块与OnStart / OnStop等合并以减少重复。

你检查过错误日志了吗? 也许你不知何故用完了计时器。 也许你可以在初始化ArchiveService时创建一个计时器并跳过OnStart的东西。

在一些项目中我和你完全一样,但没有遇到问题。

你在tickTac_Elapsed中有代码可以导致这个吗? 就像一个永不停止的循环或一些停止计时器的错误,使用线程并等待结束等等?