Stopping and starting a System.Timers.Timer - be careful you don't stop forever!
I've sometimes seen code that stops and starts a timer during its TimerElapsed event in order to ensure that the event isn't called whilst it's still being executed from a previous call. If this isn't done then you can end up with multiple instances of the handler running concurrently which is likely not what you want to happen. Now, according to the documentation:
The Timer component catches and suppresses all exceptions thrown by event handlers for the Elapsed event. This behavior is subject to change in future releases of the .NET Framework.
This holds absolutely true if your event handler looks like this:
private static void TimerElapsed(object sender, ElapsedEventArgs e) { Console.WriteLine($"{DateTime.Now.ToLongTimeString()}: Timer Elapsed - Counter: {counter}"); _timer.Stop(); DoTheRealWork(); _timer.Start(); }
And you'll end up getting output that looks something like this:
However, if it looks like this:
private static void TimerElapsed(object sender, ElapsedEventArgs e) { Console.WriteLine($"{DateTime.Now.ToLongTimeString()}: Timer Elapsed - Counter: {counter}"); _timer.Stop(); var task = Task.Run(() => DoTheRealWork()); task.Wait(); _timer.Start(); }
Then you need to make sure your DoTheRealWork method is handling all of its exceptions otherwise you'll instead see something like this:
The behaviour when there's Task.Run/Task.Wait in the mix seems to be counter to the documentation with an exception being thrown that doesn't get swallowed by the Timer component. The documentation does say "This behavior is subject to change in future releases of the .NET Framework" so even now, without Tasks in the mix it's best not to rely on the Timer to handle any exceptions for you.