System.Timers.Timer Issue

G

Guest

Hi,

I have an instance of the System.Timers.Timer class (V1.1) running in a
Windows Service. When the Elapsed event fires the Timer.Interval property is
set to 24 hours ahead, which results in the Elapsed event firing once a day.
Twice in the last 45 days the Elapsed event fired repeatedly until it was
terminated manually. The Timer.Interval is recorded in the Application Event
Log on each firing of the Elapsed event and it is correctly set to the
following day. Any recommendations on how I might proceed with correcting
this issue are greatly appreciated.

Thanks,
Ethan
 
K

Kevin Spencer

Are you saying that you are resetting the Interval each time the timer
fires? If so, why? If not, can you clarify?

--
HTH,

Kevin Spencer
Microsoft MVP
..Net Developer
You can lead a fish to a bicycle,
but it takes a very long time,
and the bicycle has to *want* to change.
 
G

Guest

Yes, that is correct. The reason is that I want the timer to fire each day at
a specific time that is configured in ap.config. So if the time is set to
2:00 PM in ap.config then the current DateTime is subtracted from the
DateTime of 2:00 PM the following day and the Interval property is set to the
resulting TimeSpan.

Ethan
 
H

Hemant Mehta

Hi Ethan,

Did you find a solution to this. I have run into the same problem.
Thought the timer interval it set to 24 hrs after 45 days the timer
started firing repeatedly until we stopped the service manually.

Thanks in advance
Hemant
 
G

Guest

We have the same issue - right down to the timer being set for 24 hours!

I have seen posts about using the Threading.Timer in place of System.Timer,
but they usually have to do with the timer not firing.

I have seen this "constant fire" state in our windows service 3 times in the
field. Each time it cripples the system and requires technical service
intervention.

I really want to get to the bottom of this issue. Do we need to start a new
thread so that someone from Microsoft sees this?
 
W

William Stacey [C# MVP]

Does System.Threading.Timer show this issue also?

--
William Stacey [C# MVP]

| We have the same issue - right down to the timer being set for 24 hours!
|
| I have seen posts about using the Threading.Timer in place of
System.Timer,
| but they usually have to do with the timer not firing.
|
| I have seen this "constant fire" state in our windows service 3 times in
the
| field. Each time it cripples the system and requires technical service
| intervention.
|
| I really want to get to the bottom of this issue. Do we need to start a
new
| thread so that someone from Microsoft sees this?
|
|
| "Hemant Mehta" wrote:
|
| >
| >
| > Hi Ethan,
| >
| > Did you find a solution to this. I have run into the same problem.
| > Thought the timer interval it set to 24 hrs after 45 days the timer
| > started firing repeatedly until we stopped the service manually.
| >
| > Thanks in advance
| > Hemant
| >
| >
| >
 
G

Guest

The problem is that I can not reproduce the state effectively in-house.
I have thought about switching to System.Threading.Timer, but I do not want
to trade one issue for another.

It seems that System.Threading.Timer has
issues with failing to fire. See:
http://support.microsoft.com/?id=900822

It may be that this other problem would be easier to "live with" than the
event-flood" I have experienced, but I would prefer to find a true fix for
this problem rather than just settling.
 
W

William Stacey [C# MVP]

Seems to effect 1.1sp1. If you on 2.0, I might just try it and see.

--
William Stacey [C# MVP]

| The problem is that I can not reproduce the state effectively in-house.
| I have thought about switching to System.Threading.Timer, but I do not
want
| to trade one issue for another.
|
| It seems that System.Threading.Timer has
| issues with failing to fire. See:
| http://support.microsoft.com/?id=900822
|
| It may be that this other problem would be easier to "live with" than the
| event-flood" I have experienced, but I would prefer to find a true fix for
| this problem rather than just settling.
|
| ---------------
|
| "William Stacey [C# MVP]" wrote:
|
| > Does System.Threading.Timer show this issue also?
| >
| > --
| > William Stacey [C# MVP]
 
G

Guest

William Stacey said:
Seems to effect 1.1sp1. If you on 2.0, I might just try it and see.

--
William Stacey [C# MVP]

| The problem is that I can not reproduce the state effectively in-house.
| I have thought about switching to System.Threading.Timer, but I do not
want
| to trade one issue for another.
|
| It seems that System.Threading.Timer has
| issues with failing to fire. See:
| http://support.microsoft.com/?id=900822
|
| It may be that this other problem would be easier to "live with" than the
| event-flood" I have experienced, but I would prefer to find a true fix for
| this problem rather than just settling.
|
| ---------------
|
| "William Stacey [C# MVP]" wrote:
|
| > Does System.Threading.Timer show this issue also?
| >
| > --
| > William Stacey [C# MVP]
 
G

Guest

Sorry for the previous botched post.

We have not yet switched to 2.0. I desperately need a patch for this
problem. Moving to 2.0 would require regression testing the rest of our
software before I could issue a patch.

What I need is someone with intimate knowledge of System.Timers.Timer and
Windows Services (and their inherent multi-threading) to try to determine how
this problem could happen.

Even if someone could provide a way to reproduce the problem on demand, I
would be in much better shape. At least I could test my patch to see if it
is effective or justify refactoring the timers in our service to another type
based on some empirical evidence.

Also, if it is reproducible, I could file a bug report with Microsoft. If
this is a problem with the System.Timers.Timer class it should be fixed for
all .NET users. If the class is correct, but my usage is a misapplication of
the System.Timers.Timer class, then something should be published to warn
developers. Based on the documentation I have seen, this code should work
for our purposes.

Thank you for any help you can provide.
 
P

Peter Bromley

Schmechel said:
What I need is someone with intimate knowledge of System.Timers.Timer and
Windows Services (and their inherent multi-threading) to try to determine how
this problem could happen.

I dont know about "Intimate" but a little reflection shows that
System.Timers.Timer uses System.Threading.Timer internally.

Also, both classes make heavy use of uint32 variables even though they
appear to provide int64 and double constructors/setters.

Unfortunately, Threading.Timers goes off to native routines so I can't
tell what the actual timer implementation is.

I would suggest that there is a int32 or uint32 overflow going on
(especially since you mentioned >45 days) so some internal variable
wraps and causes the always-on firing condition.

As a workaround, why don't you dispose the timer every time it fires and
create a new one, since it fires only once every 24 hours. Would the
minimal amount of drift this causes be a problem?

Good luck with a proper solution.
 
G

Guest

Thank you Peter. I will definitely take your advice about disposing and
recreating the timers.

Another interesting observation about this issue:

There are actually 4 timers used by this service. Their timespans can be
changed individually, but they are normally run at their defaults where three
fire once per day and one fires once per hour. They all start at the same
time and run for the life of the service.

When we have had problems, the three daily timers are all firing
continuously. The hourly timer continues to function at once per hour.

All the timers have experienced the same overall run time. There must be
some math going on internally that involves the timer interval and some
overall increasing counter.

I'm going to set up a test service to try to replicate the issue. I will
try to adjust the .NET tick-count to get to happen in less than 45 days, but
it might end up taking a while to duplicate.

Is there any way to know if the timer class uses the tick-count internally?
Does .NET reference any Win32 classes to implement the timers? Any further
advice on how to speed up the testing process would be appreciated.

Thanks again.
 
K

Kevin Spencer

Hi Schmechel,

What I do in my services is dispose and re-instantiate the timers when they
elapse. Of course, they only elapse every few minutes, and at that rate it
doesn't really affect performance. I I disposed of them every so many
milliseconds, I would look for a less-frequent solution.

--
HTH,

Kevin Spencer
Microsoft MVP
Software Composer
http://unclechutney.blogspot.com

If the Truth hurts, wear it.
 
W

William Stacey [C# MVP]

You could also opt for a cron-type solution. Have a thread that sleeps for
a minute (or until next job milliseconds) and wakes up and checks the date
on the next job to run, if it >= DateTime.Now, then run job on TP thread.
Sleep again for a minute (or until next job). This way, you have no timers
to worry about not firing or disposing them, etc. It does take a thread,
but that should not be an issue as you only need one. You also know if you
have an issue as you catch error/exit of the thread.

--
William Stacey [C# MVP]

| Hi Schmechel,
|
| What I do in my services is dispose and re-instantiate the timers when
they
| elapse. Of course, they only elapse every few minutes, and at that rate it
| doesn't really affect performance. I I disposed of them every so many
| milliseconds, I would look for a less-frequent solution.
|
| --
| HTH,
|
| Kevin Spencer
| Microsoft MVP
| Software Composer
| http://unclechutney.blogspot.com
|
| If the Truth hurts, wear it.
|
| | > Thank you Peter. I will definitely take your advice about disposing and
| > recreating the timers.
| <snip>
| > I'm going to set up a test service to try to replicate the issue. I
will
| > try to adjust the .NET tick-count to get to happen in less than 45 days,
| > but
| > it might end up taking a while to duplicate.
| >
| > Is there any way to know if the timer class uses the tick-count
| > internally?
| > Does .NET reference any Win32 classes to implement the timers? Any
| > further
| > advice on how to speed up the testing process would be appreciated.
| >
| > Thanks again.
|
|
 
G

Guest

We definitely will be moving to a better solution for handling these periodic
events in the next version.

I did, however, find the true root of the problem and I can now reproduce it.

The base problem is with the set method of the Timer.Interval property.

Background:
The Interval property is typed as double but has a check that will throw an
ArgumentException if the value is less than or equal to zero. You can set
the interval all the way up to Double.MaxValue without error. However, when
you call the Timer.Start() method, it will throw an
ArgumentOutOfRangeException if the Interval is greater than or equal
Int32.MaxValue (2,147,483,647) or less than or equal to zero. The developers
are obviously trying to protect some internal variable from a too-large
value. (Why this class is designed this way is another mystery. Perhaps
some backwards-compatibility requirement?)

The problem surfaces when you change the Timer’s interval property after the
timer is running. Internally, some math is done which involves the
Environment.TickCount (probably trying to account for the fact that the
interval value may be changed part way through the current interval).
Environment.TickCount is a Uint32 variable (max value 4,294,967,295 or 49.71
days when representing milliseconds).

If the current value of the TickCount, when combined with the new Interval
value exceeds Uint32.MaxValue, the timer will begin firing continuously until
the overflow ends. This requires either changing the Interval again or
waiting for the TickCount to reset.

To summarize, if your system has been running for less than ~25 days, there
is no way you can experience a problem. Over the next ~25 days, the safe
maximum interval set limit decreases to zero. If you exceed the limit, the
timer will fire continuously until the end of the TickCount cycle.
Because of the time relation, the larger the interval – the longer it will
misbehave. The maximum time that it can misbehave is the interval you
specified.

If the timer’s event handler updates the interval (as was my case) it will
often be less than the full interval time because the problem will not appear
until the event and subsequent setting of the interval actually occurs. (If
the Timer’s start time would be random with respect to the host computers
start time, the error time would tend towards an average of Interval/2.)
This corresponds to my observation of field failures, which occurred, on
average, within 12 hours of the system uptime reaching 50 days of uptime.
(My hourly timer would have failed also approximately 11.5 hours after the
daily timers had the service not been restarted.)

Limitations:
If you are not updating the interval, and instead using the AutoReset
feature, you will never see this problem. If you set the Interval to a value
that, when combined with TickCount, would cause an overflow, then
subsequently call the timer’s Start() method, you will not experience a
problem.

I now know how to patch my code until I can redesign the next official
version. I do want to file this bug with Microsoft. Does anyone know the
best way to do that?

If you want to investigate this problem yourself you will probably find the
“Adjust Tick Count†utility useful as it avoids a lot of waiting.
http://www.ysgyfarnog.co.uk/utilities/adjusttickcount/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top