Reputation: 242
Scenario: In a Winform application(C#), I have a Datagridview in which I have to display 4 countdown timers in the format "mm:ss". Time Interval must be 1000ms.
I was counting the timer down in the elapsed event of system.timers.timer.
On all 4 timers I'm starting to countdown from 2 mins (02:00).
Issue: It takes more time(125 seconds) than 2 mins, to reach 00:00. Similarly for 4 mins it takes 7-10 more(247 -250) seconds to reach 00:00
Upvotes: 1
Views: 846
Reputation: 50235
First off you should run this little test and see the drift in near real-time. I lose a 1 second after 72 timer elapsed events (this is with very little actual work).
using (var timer = new Timer(1000))
{
var start = DateTime.Now;
var i = 0;
timer.Elapsed += (sender, args) => Console.WriteLine("{0} -> {1}", ++i, (DateTime.Now - start).TotalMilliseconds);
timer.Start();
Thread.Sleep(130*1000);
}
I'm not sure how precise your app needs to be but you can get "good enough" by using the delta between the start time & now and subtracting that from your initial value and killing the timer at zero. You will lose seconds with this approach and there's a reasonable chance that lost second could happen @ 0:00
causing a -0:01
tick, which you will need to handle.
var countdownSeconds = 120;
var startedAt = DateTime.Now;
var timer = new Timer(1000);
timer.Elapsed += (sender, args) => Display(countdownSeconds - (int)((DateTime.Now - startedAt).TotalSeconds));
timer.Start();
//- be sure to dispose the timer
Upvotes: 0
Reputation: 14517
If you need time resolution of that type (i.e. actual clock or countdown clock), you should use the real-time clock.
You still use a timer with sub-second resolution to fire frequently enough for display purpose, but you don't add up those times, you use the real-time clock to get the real elapsed time (DateTime.Now - startTime
).
Upvotes: 0
Reputation: 9762
Timers on systems are somewhat of an inaccurate beast. Better systems generally provide better timers but even the best system has slippage.
You also need to remember that your process isn't going to be in "full control" 100% of the time, it will at times be pushed into the background and have to share the processor with other applications so whilst it's does its best to keep track of the time.
What you probably want is a High Precision Timer (aka stopwatch) in C#. Have a look at This thread and This article on selecting timer mechanisms for some more information.
Upvotes: 2