Having trouble getting expected value displayed inside a Timer.Tick()

munkyeetr

Member
Joined
Sep 28, 2007
Messages
15
Location
Canada
Programming Experience
Beginner
I am building an Interval Timer and it is working fine except that where I am displaying the seconds counting down it always skips the first second. For instance, when counting down from 10 it displays ...08...07... and doesn't change to 09 first as I am expecting.

I have been going in circles trying to flush this out and am at a loss. Any insight into why it is behaving this way would be appreciated.

intervalTime is a Date
remainingTime is a TimeSpan
tMain timer is set to tick every second

VB.NET:
        intervalHours = 0
        intervalMinutes = 0
        intervalSeconds = 10
        intervalTime = Date.Now.AddHours(intervalHours).AddMinutes(intervalMinutes).AddSeconds(intervalSeconds)
        tMain.Start()

VB.NET:
    Private Sub tMain_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tMain.Tick

        remainingTime = intervalTime.Subtract(Date.Now)
        lblTimer.Text = String.Format("{0:d2}:{1:d2}:{2:d2}", remainingTime.Hours, remainingTime.Minutes, remainingTime.Seconds)

        If intervalTime <= Date.Now Then
            tMain.Stop()
        End If

    End Sub
 
So you said your time is set to 1 second (so around 1000 ms)
Set it to 900 since you're using the timespan, it won't matter how fast it checks in between seconds This will insure you check slightly over once per second.

Keep in mind when you start the timer, the interval is the pause before the first tick too.

So if you were to say set it to 5000 it would be approximately 5 seconds before you would see the label updated.
 
Hey, CharlieMay...thanks for that suggestion. It works, but there is noticeable 'skip' in the countdown where some seconds tick off faster and others seem to pause before ticking. I wouldn't think there would be, but it is pretty obvious when watching.

One thing that works is setting the tick to 900 or 950 before starting, then changing it to 1000 inside the Timer.Tick(). That works perfectly. I would however like to find a way to not have the 'Timer.Interval = 1000' be assigned every timer tick. It is just an assignment, but I like to try to make my code as efficient as possible, and not just run redundant code over and over.

Pluggin away,
Munky
 
Actually, I think I posted too soon. Now I am (sometimes) noticing that a whole second gets skipped further in the countdown. For instance: 10...9...8...7...6...4...3...2...1, but it isn't always 5. It could be 2. Sometimes it counts down perfectly.

Back to the troubleshooting. It's frustrating because I can't use a Breakpoint and Watch because I am subtracting from the current time; As soon as it breaks, the "intervalTime <= Date.Now" test is True and the Tick is done. I am thinking I may have to count down manually.
 
The Windows.Forms.Timer is intended for use in single-threaded, Windows Forms applications. The Timer will raise its Tick event pretty much every 1000 milliseconds if you set the Interval to 1000. The thing is, because the Tick event is raised on the UI thread, your event handler will not be executed right away if the UI thread is bussy doing something else. That's the nature of single-threaded applications.

One option is to use a Timers.Timer instead. That raises its Elapsed event on a secondary thread by default. That means that your time calculation will be done pretty much exactly when you expect it to. The thing is, in order to update the UI, you will still need to delegate back to the UI thread. That means that your calculation will take place exactly when you expect it to but there may still be a delay in the result of that calculation being displayed to the user.
 
Back
Top