CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 9 of 9
  1. #1
    Join Date
    Dec 2006
    Posts
    86

    Timer going too fast

    So after letting it run for an hour, the timer seemed to be about 4 minutes too fast (i.e. after letting it count down for an hour, it finished about 4 minutes too quickly).

    I'm thinking it's in my _Tick method. I know there's an issue with the milliseconds, but I think there might be a bigger issue.

    Here's the tick method and some other info....any idea what I'm doing wrong here?


    Code:
    this.timer1.Interval = 10;
    this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
    Code:
    private void timer1_Tick(object sender, EventArgs e)
            {
                // Verify if the time didn't pass.
                if ((minutes == 0) && (hours == 0) && (seconds == 0) && (millisec == 0))
                {
                    // If the time is over, clear all settings and fields.
                    // Also, show the message, notifying that the time is over.
                    timer1.Enabled = false;
                    //MessageBox.Show(textBox4.Text);
                    button1.Enabled = false;
                    button3.Enabled = false;
                    button2.Enabled = true;
                    textBox3.Clear();
                    textBox2.Clear();
                    textBox1.Enabled = true;
                    textBox3.Enabled = true;
                    textBox2.Enabled = true;
                    textBox1.Enabled = true;
                }
                else
                {
                    // Else continue counting.
                    if (millisec < 1)
                    {
                        millisec = 59;
    
                        if (seconds < 1)
                        {
                            seconds = 59;
                            if (minutes == 0)
                            {
                                minutes = 59;
                                if (hours != 0)
                                    hours -= 1;
    
                            }
                            else
                            {
                                minutes -= 1;
                            }
                        }
                        else
                            seconds -= 1;
                    }
                    else
                        millisec -= 1;
                    // Display the current values of hours, minutes and seconds in
                    // the corresponding fields.
                    char pad = '0';
                    currentTime.Text = hours.ToString().PadLeft(2, pad)
                        + " : " + minutes.ToString().PadLeft(2, pad)
                        + " : " + seconds.ToString().PadLeft(2, pad)
                        + " . " + millisec.ToString().PadLeft(2, pad);
    
                }
            }

  2. #2
    Join Date
    Jun 2008
    Posts
    2,477

    Re: Timer going too fast

    First off, you should not be using a Timer to track real time. You can use the system time for that. A timer will not necessarily give you the resolution or repeatability you need to track real time. Your process is not always active, the CPU is context switching, and Windows is not a real time OS. If you need to track time, you can use a Timer for updates, but use the system time for your calculations.

    Also, I forget what the actual number is, but you are also not guaranteed infinite precision here. The standard Windows timing mechanism has a resolution of somewhere around 10-15 ms. So, if you set your timer to tick every 5 or ten ms it will not be predictable. Windows does expose a high performance counter (QueryHighPerformanceCounter is the Win32 function) that gives you higher granularity.

  3. #3
    Join Date
    Jun 2001
    Location
    Melbourne/Aus (C# .Net 4.0)
    Posts
    686

    Re: Timer going too fast

    The timer is fired in reaction to a WM_TIMER message reaching the front of your applications message queue. Similar to a WM_PAINT message, only one of these message types will be on your message queue at any one time and it will always be at the back of the queue. This means that your application event handler will only get fired when all other messages on the queue have been processed.

    Now imagine that there is a WM_TIMER message on your queue and for example, you are moving the mouse around over your window. The WM_MOUSEMOVE messages will keep jumping infront of the WM_TIMER message. So, if during that time another WM_TIMER message gets added to your queue, it won't, because there is already one on there. Hence, you may miss a tick.

    As Ed said, there are more reliable timers. I think the DirectX library has the most accurate one.
    Rob
    -
    Ohhhhh.... Old McDonald was dyslexic, E O I O EEEEEEEEEE.......

  4. #4
    Join Date
    Dec 2006
    Posts
    86

    Re: Timer going too fast

    BigEd, thanks for the info.

    rliq, thanks for the info about the timer class. Helps to explain a lot.


    Any websites out there with some example code snippets that I could start with? Did some google searches, but I can always use some pointers.

    Thanks.

  5. #5
    Join Date
    Jun 2008
    Posts
    2,477

    Re: Timer going too fast

    It's hard to say without knowing what you are really trying to accomplish. That doesn't look like any production quality code I have ever seen (no offense intended, I just can't think of a real life application that would use that code). Perhaps you could tell us the goal here?

  6. #6
    Join Date
    Dec 2006
    Posts
    86

    Re: Timer going too fast

    Ha.....yeah. Good question.

    Basically, I'm trying to make a stopwatch to run on a computer. When we have meetings at our company, we would use it as a count-down to the meeting start. Or, on breaks, use it as a count-down until the meeting resumes. It may need to run for hours, so it needs to be precise.

    I know there's freeware out there, but I'd like to create my own....put some company branding on it. C# is just a hobby, so I like to re-use code as much as possible....hehe.

    Any thoughts?

  7. #7
    Join Date
    May 2007
    Posts
    1,546

    Re: Timer going too fast

    So what's wrong with using DateTime.Now to check the current time...
    www.monotorrent.com For all your .NET bittorrent needs

    NOTE: My code snippets are just snippets. They demonstrate an idea which can be adapted by you to solve your problem. They are not 100% complete and fully functional solutions equipped with error handling.

  8. #8
    Join Date
    Jun 2008
    Posts
    2,477

    Re: Timer going too fast

    Ok, so you can still use a timer, but for the actual time calculations we will use the DateTime class. (As an aside, you could also use the Win32 time API's CreateWaitableTimer, SetWaitableTimer and CancelWaitableTimer. We will focus on a pure C# method).

    So, we will use a single timer to check for a single target time. In your code you will obviously need to maintain a collection of target times, but for the sake of this example we will keep it simple.

    Code:
        public partial class Form1 : Form
        {
            private Timer _timer;
            DateTime _targetTime;
    
            public Form1( )
            {
                InitializeComponent( );
                // the target time is 9:25:00 a.m. on 11/18/2009
                _targetTime = new DateTime( 2009, 11, 18, 9, 25, 0 );
                InitTimer( );
            }
    
            private void InitTimer( )
            {
                _timer = new Timer( );
                // I just chose this interval randomly, 
                // I think that ~30ms resolution is probably enough
                _timer.Interval = 30;  
                _timer.Tick += _timer_Tick;
                _timer.Start( );
            }
    
            void _timer_Tick( object sender, EventArgs e )
            {
                if ( DateTime.Now >= _targetTime )
                {
                    _timer.Stop( );  
                    MessageBox.Show( "target time has been reached" );                
                }
            }
        }
    Just plop that into a new project, change the target time if your like, and wait for the message box.

  9. #9
    Join Date
    Jun 2001
    Location
    Melbourne/Aus (C# .Net 4.0)
    Posts
    686

    Re: Timer going too fast

    I've done a similar thing before in the way that Ed said. In fact, if you are displaying the countdown on a screen in HH:MM:SS, then _timer.Interval only needs to be <500ms to maintain suitable accuracy. Obviously, firing the Timer as infrequent as possible would be best practice.
    When you come to display the HH:MM:SS, in say Ed's void _time_Tick(...) handler, ignore the actual tick count and just use the difference between DataTime.Now and _targetTime, to display the time remaining.
    Rob
    -
    Ohhhhh.... Old McDonald was dyslexic, E O I O EEEEEEEEEE.......

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured