我有一个用c#编写的Windows服务。它内部有一个计时器,可以定期激活一些功能。所以我服务的骨架:
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.我在不同服务器上的两个不同服务中使用这种方法,但两者都产生了这种行为(这就是为什么我认为它以某种方式连接到我的代码或框架本身。)
有人遇到过这种行为吗?什么可能是错的?
我编辑了这两项服务。一个人到处都有一个不错的尝试和更多的记录。第二个定期进行定时娱乐。他们都没有停止过,所以如果这种情况再持续一周,我会关闭这个问题。到目前为止,感谢大家。
我关闭了这个问题,因为什么都没发生。我的意思是我做了一些更改,但这些更改在这个问题上并不真正相关,而且从那时起这两个服务都没有任何问题。请将其标记为“已关闭且不再相关”。
答案 0 :(得分:18)
计时器中未处理的异常被吞下,他们默默地杀死计时器
将计时器代码的主体包装在try-catch块中
答案 1 :(得分:5)
我之前已经看过这个定时器和循环服务。通常情况是捕获的异常会停止计时器或循环线程,但不会在异常恢复过程中重新启动它。
对你的其他观点...... 我不认为计时器有什么“优雅”。对我来说,在代码中看到循环操作比定时器方法更直接。但优雅是主观的。
内存问题?如果你写的不正确。如果您的Thread.Sleep()设置不正确,可能会造成处理器负担。
答案 2 :(得分:4)
http://support.microsoft.com/kb/842793
这是一个已知的错误,不止一次在框架中重新出现。
最着名的解决方法:不要使用计时器。我通过做一个愚蠢的“while(true)”循环来使这个bug变得无效。
您的里程可能会有所不同,因此请使用您的OS / Framework位组合进行验证。
答案 3 :(得分:3)
有趣的问题。如果它真的只是时间相关(即不是例外),那么我想知道你是否可以简单地定期回收定时器 - 即。
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
等合并,以减少重复。
答案 4 :(得分:3)
许多受访者都指出,计时器吞下了异常。在我的Windows服务中,我使用System.Threading.Timer。它有Change(...)方法,允许您启动/停止该计时器。异常的可能位置可能是重入问题 - 如果tickTack_Elapsed执行的时间长于计时器周期。通常我会像这样编写定时器循环:
void TimeLoop(object arg)
{
stopTimer();
//Do some stuff
startTimer();
}
你也可以lock(...)
你的主循环来防止重入。
答案 5 :(得分:0)
您检查过错误日志吗?也许你不知何故用完了计时器。也许您在初始化ArchiveService时可以创建一个计时器,并跳过OnStart的东西。
答案 6 :(得分:0)
我在一些项目中与你完全一样,但没有遇到问题。
你是否在tickTac_Elapsed中有可能导致此问题的代码?就像一个永不停止的循环或一些停止计时器的错误,使用线程并等待结束等等?