Description
Description
I've found interesting behavior of System.Timers.Timer when AutoReset = false
. Looks like it's there for a while.
When Timer elapsed at least once, it starts automatically when setting any new Interval
value even though Enabled
is false
Reproduction Steps
const int TimerInterval = 100;
int elapsedTimes = 0;
using var timer = new System.Timers.Timer { AutoReset = false, Interval = TimerInterval };
timer.Elapsed += (s, e) =>
{
elapsedTimes++;
Console.WriteLine($"I'm elapsed {elapsedTimes} time(s)");
};
Console.WriteLine($"Starting timer normally");
timer.Start();
Thread.Sleep(TimerInterval * 2);
Console.WriteLine($"Setting timer interval when timer elapsed");
timer.Interval = TimerInterval;
Thread.Sleep(TimerInterval * 2);
Expected behavior
Output of the code snippet is:
Starting timer normally
I'm elapsed 1 time(s)
Setting timer interval when timer elapsed
Actual behavior
Output of the code snippet is:
Starting timer normally
I'm elapsed 1 time(s)
Setting timer interval when timer elapsed
I'm elapsed 2 time(s)
Regression?
I tracked code to the early .NET Framework versions. Looks like it has always been an issue.
Known Workarounds
Use System.Threading.Timer
instead of System.Timers.Timer
.
Configuration
Tested on .NET 8 and Windows 10.
Other information
There are inconsistent checks for current timer state. Property Enabled
setter checks for _enabled
field state and if _timer
is not null
, but Interval
property only checks if _timer
is not null
. ThenMyTimerCallback(object? state)
sets _enabled
to false
without disposing and/or setting _timer
to null
.