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

C# 带有计时器的.NET Windows服务停止响应,c#,windows-services,timer,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 *

我有一个用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_appeased函数

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

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

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


编辑: 我编辑了这两个服务。其中一个在任何地方都得到了很好的尝试和更多的记录。第二个人定期参加计时器娱乐活动。从那以后,他们都没有停止过,所以如果这种情况再持续一周,我将结束这个问题。谢谢大家到目前为止


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

是否检查了错误日志?也许你不知怎的用完了计时器。也许您可以在初始化ArchiveService时只创建一个计时器并跳过OnStart内容。

我以前在计时器和循环服务中都看到过这一点。通常情况下,捕获的异常会停止计时器或循环线程,但不会作为异常恢复的一部分重新启动它

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


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

我在一些项目中做了与您完全相同的工作,但没有出现问题


您的tickTac_中是否有可能导致此问题的代码?像一个永不结束的循环,或者某个停止计时器的错误,使用线程并等待这些线程的结束等等?

有趣的问题。如果它真的只是与时间相关的(即不例外),那么我想知道您是否可以周期性地循环使用计时器-即

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
等合并,以减少重复。

计时器中未处理的异常会被吞没,它们会自动终止计时器

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

这是一个已知的bug,它在框架中多次出现

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


您的里程数可能会有所不同,因此请使用您的操作系统/框架位组合进行验证。

正如许多受访者指出的那样,异常情况会被计时器吞没。在windows服务中,我使用System.Threading.Timer。它具有Change(…)方法,允许您启动/停止计时器。可能出现异常的地方可能是可重入性问题——以防tickTack_执行时间超过计时器周期。通常我会这样编写计时器循环:

    void TimeLoop(object arg)
    {
        stopTimer();

        //Do some stuff

        startTimer();
    }

您还可以
锁定(…)
主循环以防止重入。

计时器只创建一次。OnStart仅在我启动服务本身时运行,而不是每次它想执行某项操作时运行。不幸的是,没有。tickTack_运行正常,我会在它启动和结束时记录。每次我看到开始-停止事件对在它停止响应之前。此外,我还检查了其中的运行状态,因此它无法运行到以前启动的实例。我的最后一个想法是,我将使用VS连接到服务以调试它。希望无论发生什么情况,我都能得到例外。我还将其中一个重写为循环。值得一试。您可能希望有一个循环,定期检查计时器是否正在运行,或者检查另一个循环。我用它来自动重新启动停止的计时器或循环线程。有趣的想法,我将在本周尝试一下。对不起,我忘了提到这是一个.NET 2.0应用程序。但是我也不停止和重新启动计时器,但是有一些要考虑的问题(比如使用系统。线程代替系统。定时器)。我添加到我的列表来尝试,谢谢。我的效果和你一样——我也从未停止/重新启动过计时器。尽管如此,通过详细的日志记录,我还是能够确定计时器只是停止触发事件。根据我的经验,这个问题几乎总是由于计时器弹性委托线程的未处理异常造成的,即“Steven说了什么!”这看起来像是可怕的默认行为,但我以前也见过这种情况,我不敢相信现在仍然如此。我一直把头撞在墙上,试图弄明白为什么我的程序突然停止而没有任何消息,尽管我写了大量的日志。@spinon:我最讨厌的.net之一-这是自.net 1.0以来的一个设计缺陷,但即使12年后它仍然没有修复@Giorgi:是的-否则该方法中的任何异常(在计时器滴答声中执行)都会悄悄地终止计时器。计时器停止运行后,事件日志中有任何内容吗?什么都没有。我可以捕获tickTack_函数,但它不再被调用。因此,日志显示,从启动服务开始,我每10分钟收到一次事件,但过了一段时间,它就停止了,没有任何错误消息或错误消息