【问题标题】:System.Timers.Timer timer1_Elapsed not firing! Help!System.Timers.Timer timer1_Elapsed 未触发!帮助!
【发布时间】:2011-01-07 16:53:55
【问题描述】:

我正在创建另一个 Windows 服务,但我的计时器没有计时,我不知道为什么! 我正在使用 system.timers.timer,就像我在以前的服务中一样,它不起作用。 我已经尝试附加到它,但它似乎没有做任何事情。

我的代码:

    namespace ExpiryNotifier
{
    public partial class ExpiryNotifier : ServiceBase
    {
        public ExpiryNotifier()
        {
            InitializeComponent();
            if (!System.Diagnostics.EventLog.SourceExists("ExpiryNotifier"))
            {
                System.Diagnostics.EventLog.CreateEventSource("ExpiryNotifier", "ExpiryNotifier");
            }
            eventLog1.Source = "ExpiryNotifier";
            eventLog1.Log = "ExpiryNotifier";
        }
        private Timer timer1 = new Timer();
        protected override void OnStart(string[] args)
        {
            eventLog1.WriteEntry("Service Started");
            timer1.Elapsed += timer1_Elapsed;
            timer1.Interval = 10000;
            timer1.Enabled = true;

        }

        protected override void OnStop()
        {
            eventLog1.WriteEntry("Service Stopped");
            timer1.Enabled = false;

        }

        private void timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            eventLog1.WriteEntry("timer tick");
            timer1.Stop();

            EmailerService.EmailerService service = new EmailerService.EmailerService();
            DataSet expiringQualifications = service.GetDetailsOfExpiringQualifications();

            if(expiringQualifications.Tables[0].Rows.Count>0)
            {
                foreach(DataRow rw in expiringQualifications.Tables[0].Rows)
                {
                    if (!string.IsNullOrEmpty(rw["EmailAddress"].ToString()) )
                    {
                        if (rw["QualAwardDescription"] != null)
                        {
                            service.SendQualExpiryEmail(rw["EmailAddress"].ToString(), rw["firstName"].ToString(),
                                                        rw["QualAwardDescription"].ToString());
                        }
                    }
                }
            }


            timer1.Start();
        }
    }
}

谁能看出问题所在?

提前致谢!

贝克斯

【问题讨论】:

  • 您能看到“服务已启动”条目吗?

标签: c# windows service


【解决方案1】:

System.Timers.Timer 是一个丑陋的计时器。它所做的一件令人讨厌的事情是吞下 Elapsed 事件处理程序引发的异常。这将杀死您的计时器,因为您在输入方法时将其停止。没有任何通知,它只是停止工作。

您必须至少在此代码中添加异常处理,以便您可以记录异常并停止服务。

还要注意 OnStart() 方法中的错误,每次服务启动时,您都会不断添加事件处理程序。 Elapsed 事件会运行多次,这本身就是一种轰炸某些东西的好方法。

考虑 System.Threading.Timer,它没有任何这些问题。

【讨论】:

  • 感谢您提醒我该错误。我将其移至初始化,现在该服务实际上已经开始工作了。初始化会好吗?
  • 如果可以,那就没问题了。仅在 OnStart/Stop 中更改 Enabled。并添加异常处理。
【解决方案2】:

System.Timers.Timer.Start() 与 System.Timers.Timer.Enabled=true 功能相同; System.Timers.Timer.Stop() 与 System.Timers.Timer.Enabled=false 功能相同;

这 2 个方法在内部将 Enabled 属性设置为 true 或 false,从而启动或停止计时器。

检查您是否有权写入事件日志。您还可以检查事件日志中的错误。

System.Timers.Timer 不是线程安全的。确保正确使用它。

【讨论】:

    【解决方案3】:

    看起来它可以工作,但您可能是调试它的更好方法。谁知道你的eventLog1 是否为空

    更新您的 onstart 以包含此内容

     protected override void OnStart(string[] args)
         {
            foreach (string arg in args)
            {
                if (arg == "DEBUG_SERVICE")
                        DebugMode();
    
            }
    
         #if DEBUG
             DebugMode();
         #endif
    
         eventLog1.WriteEntry("Service Started");
         timer1.Elapsed += timer1_Elapsed;
         timer1.Interval = 10000;
         timer1.Enabled = true;
    
        }
    
    private static void DebugMode()
    {
    
        Debugger.Break();
    }
    

    现在,当您在服务上点击开始时,您会看到一个对话框,询问您是否要附加。它比尝试手动附加更容易。

    【讨论】:

    • 我已经设法让服务打勾,但我无法调试它。当我附加它时,即使它写入事件日志,它也没有遇到断点,所以我知道它正在这样做,如果我添加 debug.break 它会导致服务崩溃!
    • 没关系,它引用的是 .net 4 客户端配置文件而不是完整版本,这似乎是我无法调试的原因。
    【解决方案4】:

    我觉得timer1_Elapsed需要用到事件委托,所以

    timer1_Elapsed +=  new ElapsedEventHandler(timer1_Elapsed);
    

    http://msdn.microsoft.com/es-es/library/system.timers.timer.aspx

    虽然我会推荐 System.Threading.Timer 用于服务内部,因为它会在经过的事件中正确抛出异常。 System.Timers.Timer 只会吞下它们。

    http://msdn.microsoft.com/en-us/library/system.threading.timer.aspx

    【讨论】:

      【解决方案5】:

      请参阅下面的文件 Service.csProgram.cs 以及 事件日志...

      我注意到当项目的属性 Output Type 设置为 Windows Application 时,System.Timers.Timer 在 Windows 服务中无法正常工作。但是,当项目的属性 Output Type 设置为 Console Application 时,它确实有效。

      最快最简单的解决方案是将项目的属性输出类型设置为Console Application。当项目的属性 输出类型 设置为 Windows Application 时,控制台语句将被忽略。没有代码更改...只是项目设置更改。

      在随后的回复中,我将提交一个替代解决方案,其中 System.Timers.Timer 将在 Windows 服务中按预期运行。它涉及添加“未记录”的代码。

      为了了解发生了什么,我添加了三个断点(断点 1、断点 2 和断点 3)。断点 1 和 2 在下面的 Service.cs 中,断点 3 在下面的 Program.cs 中(参见代码中的注释:“// Breakpoint...”)。我运行了 Windows 服务,项目的属性 输出类型 设置为 Windows Application 并记录了所有结果(请参阅下面的事件日志)。

      我们看到如下(见Service.cs中的internal void TestStartupAndStop(string[] args)方法):OnStart事件触发OnStart 方法,其中定时器初始化成功(即不抛出异常)。 OnStop 事件触发 OnStop 方法,其中对象被成功地正确处理(即,不抛出异常)。但是随后,发生了完全出乎意料的事情...OnTimer 事件触发了 OnTimer 方法,其中任务成功执行了两次(即,没有抛出异常)之后服务已停止!

      ?(疯了!

      文件:Service.cs

      using System.Timers;
      
      namespace <namespace>
      {
          public partial class Service : ServiceBase
          {
              protected void OnTimer(object sender, ElapsedEventArgs e)
              {
                  var methodName = "protected void OnTimer(object sender, ElapsedEventArgs e)";
                  try
                  {
                      EventLogWriteEntry("Running Service...");
                      EventLogWriteEntry("Do Task...");
                      // :
                      // :
                      // :
                      EventLogWriteEntry("Task Done...");
                      EventLogWriteEntry("Service ran successfully.");
                  }
                  catch (Exception ex)
                  {
                      var errorMessage = "Error running Service...";
      
                      HandleGeneralException(errorMessage, ex, methodName);
                  }
              }
      
              protected override void OnStart(string[] args)
              {
                  var methodName = "protected override void OnStart(string[] args)";
                  try
                  {
                      EventLogWriteEntry("Starting Service...");
      
                      System.Timers.Timer timer = new System.Timers.Timer();
                      timer.Interval = double.Parse(ConfigurationManager.AppSettings["Timer.Interval"]); // Set Interval to 5 seconds
                      timer.Elapsed += new ElapsedEventHandler(OnTimer);
                      //timer.Enabled = true; // timer.Start() does the same exact thing
                      timer.Start();
      
                      EventLogWriteEntry("Service started successfully.");
                  }
                  catch (Exception ex)
                  {
                      var errorMessage = "Error starting Service...";
      
                      HandleGeneralException(errorMessage, ex, methodName);
                  }
              }
      
              protected override void OnStop()
              {
                  var methodName = "protected override void OnStop()";
      
                  try
                  {
                      EventLogWriteEntry("Stopping Service...");
                      EventLogWriteEntry("Do Clean-Up...");
                      // :
                      // :
                      // :
                      EventLogWriteEntry("Clean-Up Done...");
                      EventLogWriteEntry("Service stopped successfully.");
                  }
                  catch (Exception ex)
                  {
                      var errorMessage = "Error stopping Service...";
      
                      HandleGeneralException(errorMessage, ex, methodName);
                  }
              }
      
              // Note: Set project's property Output Type to Console Application.  Revert to Windows Application when done.
              // See comment in static void Main() in Program.cs
              internal void TestStartupAndStop(string[] args) // FOR TESTING PURPOSES ONLY!
              {
                  this.OnStart(args);
                  Console.WriteLine("Press ENTER to stop..."); // Console statements are ignored when Output Type is set to Windows Application.
                  Console.ReadLine();
                  this.OnStop(); // Breakpoint 1: Wait 60 seconds...
              }  // Breakpoint 2: Wait 60 seconds...
          }
      }
      

      文件:Program.cs

      namespace <namespace>
      {
          static class Program
          {
              /// <summary>
              /// The main entry point for the application.
              /// </summary>
              static void Main()
              {
                  // Note: The If block is for testing interactively.
                  // The Else block is the normal execution block of code.
                  // No need to comment/uncomment code.
                  // See comment in internal void TestStartupAndStop(string[] args) in Service.cs
                  if (Environment.UserInteractive) // FOR TESTING PURPOSES ONLY!
                  {
                      var service = new Service();
                      service.TestStartupAndStop(null);
                  }
                  else
                  {
                      ServiceBase[] ServicesToRun;
                      ServicesToRun = new ServiceBase[] 
                      { 
                          new Service() 
                      };
                      ServiceBase.Run(ServicesToRun);
                  }
              } // Breakpoint 3: Wait 60 seconds...  Timer events fired AFTER here!
          }
      }
      

      事件日志

      Level Date and Time Source Event ID Task Category Message
      Breakpoint 1: Wait 60 seconds...
      Information 5/31/2021 7:24 ServiceEventSource 0 None Starting Service...
      Information 5/31/2021 7:24 ServiceEventSource 0 None Initialize timer...
      Information 5/31/2021 7:24 ServiceEventSource 0 None Service started successfully.
      Breakpoint 2: Wait 60 seconds...
      Information 5/31/2021 7:25 ServiceEventSource 0 None Stopping Service...
      Information 5/31/2021 7:25 ServiceEventSource 0 None Do Clean-Up...
      Information 5/31/2021 7:25 ServiceEventSource 0 None Clean-Up Done...
      Information 5/31/2021 7:25 ServiceEventSource 0 None Service stopped successfully.
      Breakpoint 3: Wait 60 seconds... Timer events fired AFTER here!
      Information 5/31/2021 7:27 ServiceEventSource 0 None Running Service...
      Information 5/31/2021 7:27 ServiceEventSource 0 None Do Task...
      Information 5/31/2021 7:27 ServiceEventSource 0 None Task Done...
      Information 5/31/2021 7:27 ServiceEventSource 0 None Service ran successfully.
      Information 5/31/2021 7:27 ServiceEventSource 0 None Running Service...
      Information 5/31/2021 7:27 ServiceEventSource 0 None Do Task...
      Information 5/31/2021 7:27 ServiceEventSource 0 None Task Done...
      Information 5/31/2021 7:27 ServiceEventSource 0 None Service ran successfully.

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-13
        • 1970-01-01
        • 2012-01-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多