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

时间:2008-12-29 13:55:17

标签: c# windows-services timer

我有一个用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.我在不同服务器上的两个不同服务中使用这种方法,但两者都产生了这种行为(这就是为什么我认为它以某种方式连接到我的代码或框架本身。)

有人遇到过这种行为吗?什么可能是错的?


编辑:

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


编辑:

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

7 个答案:

答案 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中有可能导致此问题的代码?就像一个永不停止的循环或一些停止计时器的错误,使用线程并等待结束等等?