System.Timers.Timer timer1_Elapsed没有触发!救命!

时间:2011-01-07 16:53:56

标签: c# windows service

我正在创建另一个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();
        }
    }
}

有人能看到问题吗?

提前致谢!

贝克斯

5 个答案:

答案 0 :(得分:7)

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

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

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

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

答案 1 :(得分:0)

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

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

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

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

答案 2 :(得分:0)

我认为timer1_Elapsed需要使用事件委托,所以

timer1_Elapsed +=  new ElapsedEventHandler(timer1_Elapsed);

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

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

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

答案 3 :(得分:0)

它看起来很有效但你可能是一个更好的调试方法。谁知道你的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();
}

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

答案 4 :(得分:0)

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

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

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

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

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

我们看到的是以下内容(请参阅下面 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!
    }
}

事件日志

<头>
级别 日期和时间 来源 事件 ID 任务类别 留言
断点 1:等待 60 秒...
信息 5/31/2021 7:24 服务事件源 0 开始服务...
信息 5/31/2021 7:24 服务事件源 0 初始化定时器...
信息 5/31/2021 7:24 服务事件源 0 服务启动成功。
断点 2:等待 60 秒...
信息 5/31/2021 7:25 服务事件源 0 停止服务...
信息 5/31/2021 7:25 服务事件源 0 清理...
信息 5/31/2021 7:25 服务事件源 0 清理完成...
信息 5/31/2021 7:25 服务事件源 0 服务已成功停止。
断点 3:等待 60 秒...定时器事件在此处触发!
信息 5/31/2021 7:27 服务事件源 0 正在运行服务...
信息 5/31/2021 7:27 服务事件源 0 做任务...
信息 5/31/2021 7:27 服务事件源 0 任务完成...
信息 5/31/2021 7:27 服务事件源 0 服务运行成功。
信息 5/31/2021 7:27 服务事件源 0 正在运行服务...
信息 5/31/2021 7:27 服务事件源 0 做任务...
信息 5/31/2021 7:27 服务事件源 0 任务完成...
信息 5/31/2021 7:27 服务事件源 0 服务运行成功。