StopWatch Loop using VB.NET

自作多情 提交于 2019-12-10 15:25:52

问题


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


回答1:


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.




回答2:


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



回答3:


An experiment that shows that the timer should not be used for timing. It is good to use the timer to show the stopwatch elapsed time on a periodic basis.

Public Class Form1
    Private stpw As New Stopwatch
    Private WithEvents aTimer As New System.Windows.Forms.Timer

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        aTimer.Interval = 100 'ten times per second
        aTimer.Start() 'start the timer
    End Sub

    Private Sub timeTick(sender As Object, e As System.EventArgs) Handles aTimer.Tick
        If stpw.IsRunning Then
            'show that using the timer tick is not accurate for timing
            'add the number of ms. to the timespan
            'if the tick occurs exactly on the interval this will be accurate

            elapsedTM = elapsedTM.Add(New TimeSpan(0, 0, 0, 0, aTimer.Interval))

            'show the two elapsed times
            'as of .Net 4.0 format elapsed
            TextBox1.Text = stpw.Elapsed.ToString("hh\:mm\:ss\.f")
            TextBox2.Text = elapsedTM.ToString("hh\:mm\:ss\.f")

            'show the time according to the system
            TextBox3.Text = DateTime.Now.ToString("hh:mm:ss.f")
            'show the time by adding the start time and the stopwatch elapsed time
            TextBox4.Text = strt.AddMilliseconds(stpw.ElapsedMilliseconds).ToString("hh:mm:ss.f")
        End If
    End Sub

    Dim strt As DateTime
    Dim elapsedTM As TimeSpan

    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        'start
        If Not stpw.IsRunning Then
            elapsedTM = New TimeSpan(0L)
            'record the start time
            strt = DateTime.Now
            stpw.Start() 'start the stopwatch
            Button2.Select()
        End If
    End Sub

    Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
        'stop
        stpw.Stop()
        stpw.Reset()
        Button1.Select()
    End Sub
End Class


来源:https://stackoverflow.com/questions/16496309/stopwatch-loop-using-vb-net

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!