There are 2 places in my application where I use a System.Threading.Timer. The app is a Windows Service, and is deployed at several customer sites, where it runs continuously.
One timer is used to send a "Keep Alive" email message once every hour. When called, the delegate kicks off the routines that create and send the email so we know the customer installation is alive and running.
The other is used to purge unwanted log files. The app does continuous logging, and the logfile rolls over to a new logfile name at midnight, so the logs don't get too big. The trail of logs is limited to 10 days. Once a day, the log file purging routine is called by that timer's delegate. It examines all the logs in the logging directory and deletes any file found that is older than 10 days.
The code seems extremely straightforward:
Declared variables at the top of the class:
Private KeepAliveDelegate As TimerCallback
Private KeepAliveTimer As System.Threading.Timer
Start the timer in New():
KeepAliveDelegate = AddressOf KeepAliveTimerHandler
KeepAliveTimer = New System.Threading.Timer(KeepAliveDelegate, _
Nothing, _
New TimeSpan(DueTime), _
New TimeSpan(1, 0, 0))
[DueTime is a value calculated to determine the number of ticks from the present until the next clock hour, so KeepAlives come on the hour]
Timer delegate:
Private Sub KeepAliveTimerHandler(ByVal state As Object)
' Do the sending of the email
End Sub
That's all there is to it. The purging timer is equivalent, except for the parameters of the timer:
LogFilePurgeTimer = New System.Threading.Timer(LogFilePurgeDelegate, _
Nothing, _
New TimeSpan(1), _
New TimeSpan(24, 0, 0))
[This one does a purge when the Service starts, and at 24 hour intervals after]
The app has been used for over a year now and generally the timed events work just fine.
On four occasions before today (not always at the same customer site) we observed the hourly Keep Alive emails "running wild" - instead of a one hour interval, they were getting sent out at an interesting pattern of intervals. Each one has a timestamp in the log so I can say for sure that those are the intervals. The pattern would be to fire like this:
09:18:08 [10 sec]
09:18:18 [10 sec]
09:18:28 [10 sec]
09:18:38 [10 sec]
09:18:48 [10 sec]
09:18:58 [10 sec]
09:18:59 [ 1 sec]
09:19:08 [10 sec]
09:19:18 [10 sec]
09:19:28 [10 sec]
etc
Like that, without end.
Before today the solution was to just restart the Service.
Today it happened again, except that this time BOTH timers were running wild, both showing the same pattern. And the interesting thing is that restarting the Service did NOT fix it. At restart, both timers went right into the same run-wild pattern. I restarted 3 times and the behavior persisted. I then rebooted the computer and that fixed it.
How can a Timer run wild? And how could the behavior persist across a restart? Am I setting them up wrong? When I wrote them I got the syntax from a book on VB.Net
I wonder if there is something underlying, at a System level, is involved, but that is very troubling.
One timer is used to send a "Keep Alive" email message once every hour. When called, the delegate kicks off the routines that create and send the email so we know the customer installation is alive and running.
The other is used to purge unwanted log files. The app does continuous logging, and the logfile rolls over to a new logfile name at midnight, so the logs don't get too big. The trail of logs is limited to 10 days. Once a day, the log file purging routine is called by that timer's delegate. It examines all the logs in the logging directory and deletes any file found that is older than 10 days.
The code seems extremely straightforward:
Declared variables at the top of the class:
Private KeepAliveDelegate As TimerCallback
Private KeepAliveTimer As System.Threading.Timer
Start the timer in New():
KeepAliveDelegate = AddressOf KeepAliveTimerHandler
KeepAliveTimer = New System.Threading.Timer(KeepAliveDelegate, _
Nothing, _
New TimeSpan(DueTime), _
New TimeSpan(1, 0, 0))
[DueTime is a value calculated to determine the number of ticks from the present until the next clock hour, so KeepAlives come on the hour]
Timer delegate:
Private Sub KeepAliveTimerHandler(ByVal state As Object)
' Do the sending of the email
End Sub
That's all there is to it. The purging timer is equivalent, except for the parameters of the timer:
LogFilePurgeTimer = New System.Threading.Timer(LogFilePurgeDelegate, _
Nothing, _
New TimeSpan(1), _
New TimeSpan(24, 0, 0))
[This one does a purge when the Service starts, and at 24 hour intervals after]
The app has been used for over a year now and generally the timed events work just fine.
On four occasions before today (not always at the same customer site) we observed the hourly Keep Alive emails "running wild" - instead of a one hour interval, they were getting sent out at an interesting pattern of intervals. Each one has a timestamp in the log so I can say for sure that those are the intervals. The pattern would be to fire like this:
09:18:08 [10 sec]
09:18:18 [10 sec]
09:18:28 [10 sec]
09:18:38 [10 sec]
09:18:48 [10 sec]
09:18:58 [10 sec]
09:18:59 [ 1 sec]
09:19:08 [10 sec]
09:19:18 [10 sec]
09:19:28 [10 sec]
etc
Like that, without end.
Before today the solution was to just restart the Service.
Today it happened again, except that this time BOTH timers were running wild, both showing the same pattern. And the interesting thing is that restarting the Service did NOT fix it. At restart, both timers went right into the same run-wild pattern. I restarted 3 times and the behavior persisted. I then rebooted the computer and that fixed it.
How can a Timer run wild? And how could the behavior persist across a restart? Am I setting them up wrong? When I wrote them I got the syntax from a book on VB.Net
I wonder if there is something underlying, at a System level, is involved, but that is very troubling.