Question

In relation to a previous question of mine ([question] : Which thread will timer method run in? ), I've added a Timer to my Windows Forms app to run every 100ms to show how long the program session has been running. I've defined it as follows (these are only the snippets relevant to the timer):

private System.Timers.Timer timerPureTime = new System.Timers.Timer(100);


timerPureTime.Elapsed += new System.Timers.ElapsedEventHandler(updateTimeElapsed);
this.timerPureTime.SynchronizingObject = currentForm; //where currentForm is my main Form

public void updateTimeElapsed(object sender, ElapsedEventArgs e)
    {
        if (currentForm.lblTimeElapsed.InvokeRequired) //lblTimeElapsed is your standard Windows Form label
        {
            currentForm.lblTimeElapsed.Invoke((MethodInvoker)delegate  //also, trying to make make GUI invoking thread-safe here
            {
                TimeSpan t = TimeSpan.FromSeconds(purelyTime);
                string showTime = string.Format("{0:D2} min {1:D2} sec",
                    t.Minutes,
                    t.Seconds);
                currentForm.lblTimeElapsed.Text = showTime;
            });
        }
        else
        {
            TimeSpan t = TimeSpan.FromSeconds(purelyTime);
            string showTime = string.Format("{0:D2} min {1:D2} sec",
                t.Minutes,
                t.Seconds);
            currentForm.lblTimeElapsed.Text = showTime;
        }
        purelyTime += 0.1;
    }

As I understand it the Timer should be running in a thread of its own (taken from the Threadpool) however it still experiences some delay every now and then, throwing the timer off-course. Other threads within the application run pretty regularly (every 250ms) and computation-intensive, but shouldn't these be independent of Timer threads?

What could be the possible causes for timer lag in such cases?

Was it helpful?

Solution

Windows cannot guarantee a precisely regular callback for a timer, so you will definitely see that kind of variance.

You need to take a different approach:

  1. Initialise a Stopwatch field in your class.
  2. Call Stopwatch.Restart() when you want to reset the timing.
  3. Inside updateTimeElapsed() use Stopwatch.Elapsed instead of purelyTime.

Note that your code is completely ignoring the amount of time spent in the timer handler function itself. Inside the handler, you are using Invoke to send a message to the UI and waiting for it to return. That can take an arbitrary amount of time, particularly if the UI is busy.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top