6 Replies - 5445 Views - Last Post: 28 February 2011 - 06:02 PM

#1 iansavell  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 9
  • Joined: 14-December 10

Accuracy of .NET timers (NOT)

Posted 03 February 2011 - 07:41 AM

Does anyone have any ideas on creating an accurate timer in .NET, esp vb.net?

My problem is I'm writing an app that controls external hardware using a state machine. I'm replacing code written over 10 years ago in a much earlier version of VB.

Certain things have to happen at certain times, so after a bit of research I used the system.timers.timer class to increment a millisecond counter and fired actions as the counter incremented past the due time. As I needed sub 1 second accuracy I used a 100ms interval for that timer.

The system ran terribly slow, by about 3 sec each minute. Another poster on this forum noticed this a month ago with the system.windows.forms timer and was directed to other "more accurate" timers. I already recognised that and thought a few milliseconds error in the system.timers.timer would be OK. What I didn't realise was that the error is PER TICK so it accumulates very fast.

To see this in practice, create a form with a button and two checkboxes and add this code
Public Class frmTimerTest

    Private MyTimer As System.Timers.Timer
    Private MyTime As Integer
    Private TimeNow As Date

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        'set up the timer and clock
        MyTimer = New System.Timers.Timer()
        AddHandler MyTimer.Elapsed, AddressOf MyTimerTick
        MyTimer.Interval = 100 'play with this to see accuracy goes up as interval goes up
        MyTimer.AutoReset = True
        MyTimer.SynchronizingObject = Me
        TimeNow = TimeOfDay()
        MyTimer.Start()
    End Sub

    Private Sub MyTimerTick(ByVal sender As Object, ByVal e As EventArgs)
        MyTime += MyTimer.Interval
        TextBox1.Text = CInt(MyTime / 1000)
        TextBox2.Text = (TimeOfDay() - TimeNow).TotalSeconds
    End Sub

End Class



Run the form, click the button (while watching a real clock if you like) and watch the numbers in the two textboxes go out of sync. From the earlier poster I guess the timer always runs slow. I estimate there is an average error of about +7ms per tick.

So I've modified my app so instead of waiting for the incremented time to reach the next event, it sets the timer interval directly to the next event time. That way I get just a few ms error each event, but over a number of starts it still ends up a second slow, which may not seem much but will undoubtedly lead to complaints.

My next option is to use the timer just as a way of generating ticks and in the tick handler use the system clock to determine the true time. Only issue there is everything has to be in increments of 1 sec which isn't ideal, some events are separated by 0.5 or 1.5 sec.

I could use the "multimedia timer" but getting it into VB.NET doesn't look easy, and I've seen suggestions it isn't available in Win7. Annoyingly, the old VB app used a built-in "timer" function which free ran through the app and apparently provided absolute accuracy.

What do other people do?

Ian.

Is This A Good Question/Topic? 0
  • +

Replies To: Accuracy of .NET timers (NOT)

#2 RudiVisser  Icon User is offline

  • .. does not guess solutions
  • member icon

Reputation: 1003
  • View blog
  • Posts: 3,562
  • Joined: 05-June 09

Re: Accuracy of .NET timers (NOT)

Posted 25 February 2011 - 07:11 AM

This may be a long shot but have you looked into using a Thread to perform your accurate operations??

I've never had those go massively out of sync and the code shouldn't require that much modification (just make sure you're invoking any changes to Controls on the correct thread).
Was This Post Helpful? 1
  • +
  • -

#3 iansavell  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 9
  • Joined: 14-December 10

Re: Accuracy of .NET timers (NOT)

Posted 25 February 2011 - 08:32 AM

Rudi

System.timers.timer runs in a thread but on expiry it has to break back into the UI thread to trigger the UI code and have the count reset. As you suggest, that is probably where the error comes in. I guess I could free-run a ticking timer in a thread and have that thread signal the UI when something needs doing, so there's no delay in resetting. I guess I don't know enough about multi-threading code to do that.

What I've actually done is to set up a number of timers, mostly dedicated to a particular task and kicking off that task when they expire. Non-critical timers for things like turning off a warning light after 1.5 sec or flashing a strobe. are just not accurate, but the don't need to be. However, a master timing routine using the system clock controls the whole system so repeated events don't drift over time.

Thanks, Ian
Was This Post Helpful? 0
  • +
  • -

#4 RudiVisser  Icon User is offline

  • .. does not guess solutions
  • member icon

Reputation: 1003
  • View blog
  • Posts: 3,562
  • Joined: 05-June 09

Re: Accuracy of .NET timers (NOT)

Posted 25 February 2011 - 02:36 PM

Unfortunately I don't do VB.NET, but I'm sure you could convert this example :)

The basic idea is that everything can run on the separate thread, so you will do your sleeping (timeouts) there, and then 'Invoke' other code on the main thread, which updates the controls.

This code, for 15 iterations over 100ms period, totalling 1.5 seconds, got a total (actual) time of: 1.5070862
Is that good? :/ Only a 0.007 second deviation for 15 iterations..

    public partial class Form1 : Form
    {
        private int MyTime;
        private int Interval = 100;
        private DateTime timeClicked;

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Thread t = new Thread(new ThreadStart(threadAction));
            t.Start();
            timeClicked = DateTime.Now;
        }

        private void threadAction()
        {
            for (int i = 0; i < 15; i++)
            {
                Thread.Sleep(Interval);
                MyTime += Interval;
                this.Invoke((ThreadStart)delegate()
                {

                    textBox1.Text = (MyTime).ToString();
                    textBox2.Text = (DateTime.Now - timeClicked).TotalSeconds.ToString();
                });
            }
        }
    }

This post has been edited by RudiVisser: 25 February 2011 - 02:37 PM

Was This Post Helpful? 1
  • +
  • -

#5 raziel_  Icon User is offline

  • Like a lollipop
  • member icon

Reputation: 464
  • View blog
  • Posts: 4,255
  • Joined: 25-March 09

Re: Accuracy of .NET timers (NOT)

Posted 28 February 2011 - 04:51 PM

if i want accuracy i use GetTickCount64

This post has been edited by NoBrain: 28 February 2011 - 04:55 PM

Was This Post Helpful? 0
  • +
  • -

#6 raziel_  Icon User is offline

  • Like a lollipop
  • member icon

Reputation: 464
  • View blog
  • Posts: 4,255
  • Joined: 25-March 09

Re: Accuracy of .NET timers (NOT)

Posted 28 February 2011 - 04:57 PM

if you want i can show you how you can make a timer using this api function.
EDIT: You know that while your debugging stuff up things move slower then if you run it trough the executable?

This post has been edited by NoBrain: 28 February 2011 - 05:01 PM

Was This Post Helpful? 0
  • +
  • -

#7 SixOfEleven  Icon User is offline

  • using Caffeine;
  • member icon

Reputation: 945
  • View blog
  • Posts: 6,342
  • Joined: 18-October 08

Re: Accuracy of .NET timers (NOT)

Posted 28 February 2011 - 06:02 PM

The Stopwatch class is more reliable that the Timer's tick event. I'm not sure how you would implement it in VB.NET 100%. I've used it in C# for timing in games which usually should be more reliable than the resolution of the Tick event of a timer. Even better, look into the System.Diagnostics.PerformanceCounter, it has a much higher resolution than Timer from what I can tell.

*edit*
Check out the link below for an example.
http://allapi.mental...DA18F12B54.html

This post has been edited by SixOfEleven: 28 February 2011 - 06:10 PM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1