System.Timers.Timer timer1_Elapsed not firing! Hel

2019-02-26 11:34发布

问题:

I am creating another windows service and my timer is not ticking and I have no idea why! I am using system.timers.timer as I have in previous services and it doesn't work. I have tried attaching to it but it doesn't seem to do anything.

My code:

    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();
        }
    }
}

Can anyone see the problem?

Thanks in advance!

Bex

回答1:

System.Timers.Timer is an ugly timer. One nasty thing it does is swallow exceptions raised by the Elapsed event handler. Which will kill your timer since you stop it when entering the method. No notification whatsoever, it just stops working.

You have to at least add exception handling to this code so you can log the exception and stop the service.

Also beware the bug in your OnStart() method, you'll keep adding an event handler each time the service gets started. The Elapsed event runs multiple times, in itself a good way to bomb something.

Consider System.Threading.Timer, it doesn't have any of these problems.



回答2:

System.Timers.Timer.Start() has a same function as System.Timers.Timer.Enabled=true; System.Timers.Timer.Stop() has a same function as System.Timers.Timer.Enabled=false;

Those 2 methods internally sets Enabled property to true or false which starts or stops the timer.

Check if you have permission to write to eventlog. You can also check for errors in eventlog.

System.Timers.Timer is not thread safe. Make sure you use it properly.



回答3:

It looks like it works but you probably a better way to debug it. Who knows maybe your eventLog1 is null

Update your onstart to include this

 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();
}

Now when you hit start on the service you'll get a dialog asking if you want to attach. Its way easier then trying to attach manually.



回答4:

I think timer1_Elapsed needs to use the event delegate, so

timer1_Elapsed +=  new ElapsedEventHandler(timer1_Elapsed);

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

Though I would recommend the System.Threading.Timer for inside a service, as it will correctly throw exceptions inside the elapsed event. System.Timers.Timer just swallows them.

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