I want to create a simple timer with this interface using VB.NET
I want to press Button1 and to start counting seconds in the textbox.
I do not want to use the Timer Component because it does not offer high resolution.
So, I decided to use a stopWatch Class due to its high resolution according to specifications.
But according to my VB.NET code below it seems to me that the whole "dotnet adventure" is impossible. That is because when I press Button1 the whole form it freezes and I cannot press Button2 to stop the timer.
Is there anything wrong with my code? What should I do to have the functionality described above?
Thanks in advance!
Public Class Form1
Private enableTime As TimeSpan
Private stopWatch As New Stopwatch()
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
stopWatch.Start()
If stopWatch.IsHighResolution Then
Do
If stopWatch.ElapsedTicks.Equals(TimeSpan.TicksPerSecond) Then
enableTime = enableTime + TimeSpan.FromSeconds(1)
TextBox1.Text = enableTime.ToString
stopWatch.Restart()
End If
If Not stopWatch.IsRunning Then
Exit Do
End If
Loop
End If
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
stopWatch.Stop()
stopWatch.Reset()
End Sub
End Class
In WinForms, there is one UI thread executing the message loop. Basically, every event is added to the message queue, which is processed, one event after another. When Button1
is clicked, the Button1_Click
method is executed and no other event will be processed until it finishes. Since your design requires Button2.Click
to be processed in order to terminate the loop in Button1.Click
, it will never terminate.
To correctly implement what you want, you'd have to start the stopwatch on Button1.Click
and put the UI update logic into the Tick
event of a timer which you place on the form.
You are "losing" time because you're manually adding to a timespan: enableTime = enableTime + TimeSpan.FromSeconds(1)
. The Stopwatch() itself is always accurate when you use its Stopwatch.Elapsed
property. All you need to do is update the GUI from a Timer.Tick
event. Basically the Timer just asks the Stopwatch what the current time is and displays it...no calculations needed.
The following will update ten times a second, will not "drift", and will not peg the CPU:
Public Class Form1
Private SW As New Stopwatch
Private WithEvents Tmr As New System.Windows.Forms.Timer
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Tmr.Interval = 100
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
SW.Start()
Tmr.Start()
End Sub
Private Sub Tmr_Tick(sender As Object, e As System.EventArgs) Handles Tmr.Tick
TextBox1.Text = SW.Elapsed.ToString
End Sub
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
SW.Stop()
Tmr.Stop()
SW.Reset()
End Sub
End Class
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With