Windows服务应用程序挂起

时间:2011-03-13 08:01:14

标签: c# .net windows service timer

背景:
- 运行Window Server 2008 R2 - 服务器已经修补了所有最近的更新 - 服务器运行在.NET 3.5中构建的5个服务,所有这些服务都使用计时器重复检查数据库(大多每10秒)。
- 这些服务不是CPU / RAM密集型的 - 服务器没有任何性能和资源问题或瓶颈。

在大多数情况下,一切都按预期工作,但有时(或所有)服务只是停止工作。我正在将所有应用程序异常记录到文件中,但在失败时没有。事件记录器中也没有错误,服务管理器将服务视为正在运行。我必须停止服务并再次启动它们以恢复功能。

此行为无法预测,有时需要一周或一个月才能停止工作。此外,有时服务会同时“死”或同时“死”。

只有我想到的是Timer对象。我一直在使用System.Timers.Timer并发现几个论坛帖子说明它不可靠,因为垃圾收集器可能释放实例。我尝试使用GC.KeepAlive()保留它无济于事。我已经遵循了一些关于将System.Timers.Timer移动到System.Threading.Timer的建议,但这也没有任何区别。

此刻,我迫不及待地想知道这种行为的来源。有没有已知的类似问题?如果没有引发异常并且事件日志也是静默的,我该如何调试它?

感谢您提供任何可能导致任何解决方案的建议。

更新:包括当前状态的裸机代码:

private System.Threading.Timer timerPublish = null;
private bool timerDelegateMethodRunning = false;

protected override void OnStart(string[] args)
{
    SetupTimer();
}

protected override void OnStop()
{
    if (timerPublish != null)
    {
        timerPublish.Dispose();
    }
}

public void SetupTimer()
{
    if (timerPublish != null)
    {
        timerPublish.Dispose();
    }
    TimerCallback callbackMethod = new TimerCallback(this.timerPublish_Elapsed);
    timerPublish = new System.Threading.Timer(callbackMethod, null, 5000, 5000);
}

void timerPublish_Elapsed(Object stateInfo)
{
    if (timerDelegateMethodRunning)
    {
        return;
    }
    timerDelegateMethodRunning = true;

    try
    {
        // Processing code here
    }
    finally
    {
        timerDelegateMethodRunning = false;
    }
}



更新2:谢谢你们的见解和建议。一旦问题再次发生,我将尝试调试生产服务器上的服务。我会在有任何新内容(可能在几周内)后立即报告。

3 个答案:

答案 0 :(得分:3)

为什么让事情复杂化? :)准备好后,只需使用Timer.Change()方法再次触发计时器。

另请注意,WorkerMethod 中的任何未捕获的例外情况都会 f * ckup您的服务。

public class YourService
{
    private System.Threading.Timer _timer;

    protected override void OnStart(string[] args)
    {
        //run once in 5 seconds.
        _timer = new System.Threading.Timer(WorkerMethod, null, 5000, Timeout.Infinite);
    }

    protected override void OnStop()
    {
        if (_timer != null)
        {
            _timer.Dispose();
            _timer = null;
        }
    }

    void WorkerMethod(object state)
    {
        // Processing code here

        _worker.Change(5000, Timeout.Infinite); //Run again in 5 seconds
    }
}

更新

我看到你在哪里使用System.Timers.Timer。最大的问题是 忽略异常 。也就是说,如果您的代码抛出异常并且您没有抓住它: 您将永远不会意识到该异常 。这可能是你的问题。

答案 1 :(得分:1)

在你知道挂起的原因之前,不要过早得出结论。可能有各种令人难以置信的因素,但转储分析或实时调试可以说实话,

http://blogs.msdn.com/b/tess/archive/2006/10/16/net-hang-debugging-walkthrough.aspx

如果您愿意,您甚至可以通过http://support.microsoft.com

打开支持案例

答案 2 :(得分:0)

无论如何,我可能会建议你的服务略有改变;在我们有readonly Timer的地方,在初始分配后,只需要切换来运行,而不是在某一刻发生处理的方式,并保留我们自己的硬引用TimerCallback。至少,我们将对象的处理留给服务本身(至少是我们困扰的长期对象)。

虽然这种模式可能不是你手套的白兔,但我可以保证以这种方式构建的许多服务的可靠性。因此,如果问题在实施后仍然存在,那么我会非常自信地说// Processing code here后面的内容本身就存在问题。

private readonly System.Threading.Timer Timer = null;
private readonly System.Threading.TimerCallback Callback = null;
private readonly int Interval = 5000;

public MyService()
{
    Callback = new TimerCallback(this.timerPublish_Elapsed);
    Timer = new System.Threading.Timer(Callback, null, Timeout.Infinite, Timeout.Infinite);
}

private void Start()
{
    Timer.Change(Timespan.Zero, Interval);
}

private void Stop()
{
    Timer.Change(Timeout.Inifinite, Timeout.Inifnite);
}

protected override void OnStart(string[] args)
{
    Start();
}

protected override void OnStop()
{
    Stop();
}

public void Dispose()
{
    Dispose(true);
    GC.SuppressFinalize(this);
}

private void Dispose(bool disposing)
{
    if(disposing)
    {
        if(Timer != null)
            Timer.Dispose();
    }
}