Writing a more efficient clock function
-
06-07-2019 - |
Question
I have a clock feature in a VB.NET program that displays the time including the seconds. I currently have a timer constantly polling using NOW. I have to poll the system clock quite often because I need to have the second update in sync with the system clock.
Is there a more direct to access the time only when the seconds change?
Is there a more efficient way to write this code?
If you need more info let me know.
Solution
Why not use the timer component? This assumes that you are using a GUI and not building a service.
You could call a synchronization routine that performed the polling to get the timer very close to the seconds changing, then delegate to the timer. You could call the sync routine once a minute or so to make sure that you aren't getting any OS drift.
That being said, I'm sure there is a way to detect the seconds changing event, I just don't know how to do it.
Update:
This link has an implementation similar to what I was envisioning. Just modify it so that you are not permanently stuck in a loop and voila! You have your sync routine.
Update 2:
Based on feedback from Shog9, I think this might be a better approach than polling:
Public Class Form1
Private WithEvents clockTimer As New Timer
Private currentTime As DateTime = DateTime.MinValue
Private Sub ClockTick(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles clockTimer.Tick
UpdateTimer()
DisplayTimer()
End Sub
Private Sub UpdateTimer()
currentTime = DateTime.Now
clockTimer.Stop()
clockTimer.Interval = 1000 - currentTime.Millisecond
clockTimer.Start()
End Sub
Private Sub DisplayTimer()
lblTime.Text = currentTime.ToString("T")
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
UpdateTimer()
DisplayTimer()
End Sub
End Class
Now, based on my preliminary tests, there is some sort of drift with each Tick event. On my machine, it varied between 12 and 20 milliseconds. If anyone has an idea on how to reliably correct the drift, I would be interested in learning.
OTHER TIPS
Use a Timer object, set it's "interval" to 0, set it's "enabled" to true. That will fire roughly every 15 milliseconds (based on your hardware configuration). In that method, set MyLabel.Text = DateTime.Now.ToString() (or whatever you're doing).
That is perfectly performant.