【问题标题】:Windows Service application hangsWindows 服务应用程序挂起
【发布时间】:2011-03-14 07:27:29
【问题描述】:

背景:
- 运行 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;
    }
}



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

【问题讨论】:

  • 您需要做更多的调查,然后才能就此提出任何问题。这是大海捞针。缩小它做了一些。
  • 你的意思是什么调查?在尝试自己解决几个月后,我已经走到了死胡同。我正在将服务执行的所有操作、每个计时器滴答/经过的事件等记录到文件中。它只是停止在日志文件中放置任何内容,并且服务从那时起就无法工作。
  • 为了隔离您的问题,我建议编写一个简短的程序,希望能重现该问题。如果您可以使用任一 Timer 类来重现它,请将计时器代码替换为本地开发的代码,以查看是否可以解决该问题。我建议初学者在后台线程中进行十秒睡眠的循环(这很容易)。或者,您可以使用 Monitor 和 Pulse。如果您隔离并重现计时器错误,请将此代码提交给问题,并可能作为错误提交给 Microsoft...
  • 发布启动计时器的功能,以便我们了解您的使用情况。
  • Gabe:我在处理代码以及任何循环或循环中记录每一个动作。所有数据库和/或网络请求都将超时设置为最多 20 秒。此外,当这些服务没有响应时,它们没有活动的 CPU 使用率。最后一条线索 - 如果某些服务死亡,它通常会同时发生在其他一些(或全部)身上。不过,系统服务运行良好。

标签: c# .net windows service timer


【解决方案1】:

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

还知道WorkerMethod 中任何未捕获的异常都会搞砸你的服务。

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。它最大的问题是它忽略异常。也就是说,如果您的代码抛出异常而您没有捕获它:您将永远不会意识到该异常。这很可能是你的问题。

【讨论】:

    【解决方案2】:

    在了解挂起的原因之前,切勿过早下结论。可能有各种令人难以置信的因素,但转储分析或实时调试可以告诉你真相,

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

    如果您愿意,您甚至可以通过 http://support.microsoft.com 打开支持案例

    【讨论】:

      【解决方案3】:

      无论如何,我可能会为您的服务建议稍微改变一下模式;我们有一个readonlyTimer,在初始分配之后,它只是让 toggled 运行,而不是现在发生的处理方式,并且还保留我们自己对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();
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-09-01
        • 2011-03-13
        • 2020-06-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-10
        • 1970-01-01
        相关资源
        最近更新 更多