【问题标题】:System.Threading.Timer not ticking on Windows Server 2003System.Threading.Timer 在 Windows Server 2003 上不运行
【发布时间】:2011-10-20 00:44:14
【问题描述】:

我目前在将我的 Windows 服务部署到 Win2k3 服务器时遇到了 System.Threading.Timer 问题。当我安装它时,它在我的本地机器上每秒都可以正常工作(出于调试目的过度杀伤),但是在我将它安装到服务器之后,服务成功启动然后永远不会触发一次计时器事件。有没有人遇到过类似的情况?我的大部分研究都发现了从很久以前就在 .NET 1.1 中明显普遍存在的问题。感谢您的时间和帮助。

   protected override void OnStart(string[] args)
   {
        int interval = Int32.Parse(ConfigurationManager.AppSettings["SleepTime"]) * 1000;
        TimerCallback cb = new TimerCallback(ProcessTimerEvent);
        QueueWorker worker = new QueueWorker();
        workTimer = new Timer(cb, worker, interval, 1000);

    }
    private static void ProcessTimerEvent(object obj)
    {
        if (obj is QueueWorker)
        {
            QueueWorker qw = (QueueWorker)obj;
            qw.doWork();
        }
    }
    class QueueWorker
    {
        public void doWork()
        {
           // work happening here
        }
    }

更新:

我发现它与服务需要运行的用户有关。当服务作为系统运行时,线程工作得很好。任何人都知道用户需要哪些权限才能运行线程?我尝试在本地安全设置中使用“作为操作系统的一部分”,但这只会导致服务启动,然后在以我添加的用户身份登录时立即失败。

【问题讨论】:

  • 非常明显的问题:服务器上SleepTime 的 app.Config 值是多少?其他选项:改用System.Timers.Timer
  • 在以这种方式实现之前,我有一个 System.Timers.Timer。我在我的服务器上得到了相同的行为,服务将启动,然后计时器事件将永远不会触发。然后我读到 Win 2k3 服务器做了一些有趣的线程处理,而 Timer 可能无法按我的预期工作。出于我的测试目的,现在的 SleepTime 值是 1 秒。稍后,当我不测试时,它将成为我需要的任何东西。
  • 你能发布关于 w2k3 行为的链接吗?你能建立一个控制台测试应用程序来排除赢服务的东西吗?使用Console.WriteLine 进行测试也会更容易。而且,很抱歉提出愚蠢的问题,SleepTime 是 1000 毫秒 = 1 秒,对吧?
  • 我可能会构建一个控制台测试应用程序,但我认为 Win2k3 服务器的问题在于服务中的线程是一开始的问题。是的,1000 毫秒 = 1 秒。

标签: c# .net timer


【解决方案1】:

计时器可能正在触发。你可以在目标机器上运行DebugView:

http://technet.microsoft.com/en-us/sysinternals/bb896647.aspx

然后你可以在你的代码中调用,看看是这样执行的:

System.Diagnostics.Debug.WriteLine("Beginning of Timer event...");

System.Diagnostics.Debug.WriteLine("End of Timer event");

【讨论】:

  • 我有一条要触发的事件消息,但我什么也没得到。计时器内部的工作也没有完成。我在没有计时器的情况下安装了它,只运行了 doWork() 部分,它的行为与我预期的一样,甚至在它应该写到事件日志的地方。所以这完全与定时器和线程有关。
  • 我想知道运行该服务的用户是否无权访问:ConfigurationManager.AppSettings["SleepTime"]?这没有意义,但您可以硬编码一个值而不是读取它,看看是否有帮助。
  • @mtgibbs21:我还建议确保OnStart 方法确实按您的预期启动计时器。您应该输入一些代码,在调用OnStart 时输出一条消息,interval 的值,以及当OnStart 退出时。在我看来,计时器没有被创建。
  • interval 值已正确填充,并且在以我的用户身份运行时正在实例化计时器。只是由于某种原因,OnStart 方法刚刚完成到最后,并且线程永远不会为计时器启动。同样,以Local System 运行服务解决了定时器未启动但不再作为执行其工作所需的用户运行的问题。
  • 我也已将此用户添加到机器上的本地管理员,但这似乎没有帮助。
【解决方案2】:

我可以提出几个解决方案:

  1. 使用控制台应用程序而不是 Windows 服务。从任务计划程序运行您的控制台应用。
  2. 构建您自己的计时器类。使用您自己的线程并在轮询间隔内休眠。醒来后,做你的工作。然后再睡。

为了完整起见,这里有一些详细描述实际错误的文章:

【讨论】:

  • 这是一个很好的信息汇编。我将把它标记为解决方案,以便人们知道阅读这些内容。
【解决方案3】:

好的。感谢您对此提出的所有建议。我制定了一个非常激进的日志方案,我相信服务器出于某种原因正在杀死我的线程。我添加了一个GC.KeepAlive(workTimer),它似乎已经解决了计时器不滴答的问题。

以防万一其他人遇到此问题,在我看来本地系统获得线程优先级,但其他用户可能会因某种原因而破坏他们的线程。由于我无法完全访问我正在部署它的服务器,因此我会将修复程序归咎于 KeepAlive 或服务器团队在我背后修复了一些问题。

【讨论】:

  • 很高兴您找到了使其工作的方法。我已经发布了一些其他可能的解决方案,它们可能对您有帮助,也可能对您没有帮助(但可能对其他人)。以及一些详细介绍该错误的文章。
猜你喜欢
  • 2012-10-23
  • 2015-09-02
  • 1970-01-01
  • 1970-01-01
  • 2010-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多