Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Clock drift. Very typical for trivial timers. The reason for this is that they are typically implemented using a sleep function. A sleep function is always guaranteed to sleep for at least the time specified but not guaranteed to not sleep for more time than that, in practice it's always accumulating a drift.</p> <p>There are ways to write timer that compensate for the drift and on average hit the target.</p> <p>One of my favorite timers are fixed step ones, that have a discreet tick. It's very simple and looks like this:</p> <pre><code>var t = DateTime.Now + TimeSpan.FromSeconds(1); for (;;) { if (DateTime.Now &gt;= t) { t += TimeSpan.FromSeconds(1); // Tick! } } </code></pre> <p>That's a crude but effective timer, this following one is an example of a clock I built for a WPF timer where the built in timer was suffering from drifting. This timer is a lot more complex and it does not hog your CPU. But it clearily illustrates typical issues that timers have.</p> <p>The OnTimerTick here is using a built in timer that suffers from drift but it's adjusting the interval to compensate for the drift.</p> <pre><code>/// &lt;summary&gt; /// Occurs when the timer interval has elapsed. /// &lt;/summary&gt; public event EventHandler Tick; DispatcherTimer timer; public bool IsRunning { get { return timer.IsEnabled; } } long step, nextTick, n; public TimeSpan Elapsed { get { return new TimeSpan(n * step); } } public FixedStepDispatcherTimer(TimeSpan interval) { if (interval &lt; TimeSpan.Zero) { throw new ArgumentOutOfRangeException("interval"); } this.timer = new DispatcherTimer(); this.timer.Tick += new EventHandler(OnTimerTick); this.step = interval.Ticks; } TimeSpan GetTimerInterval() { var interval = nextTick - DateTime.Now.Ticks; if (interval &gt; 0) { return new TimeSpan(interval); } return TimeSpan.Zero; // yield } void OnTimerTick(object sender, EventArgs e) { if (DateTime.Now.Ticks &gt;= nextTick) { n++; if (Tick != null) { Tick(this, EventArgs.Empty); } nextTick += step; } var interval = GetTimerInterval(); Trace.WriteLine(interval); timer.Interval = interval; } public void Reset() { n = 0; nextTick = DateTime.Now.Ticks; } public void Start() { var now = DateTime.Now.Ticks; nextTick = now + (step - (nextTick % step)); timer.Interval = GetTimerInterval(); timer.Start(); } public void Stop() { timer.Stop(); nextTick = DateTime.Now.Ticks % step; } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload