使用 VB.NET 的秒表循环
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16496309/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
StopWatch Loop using VB.NET
提问by Novemberland
I want to create a simple timer with this interface using VB.NET
我想使用 VB.NET 用这个界面创建一个简单的计时器


I want to press Button1 and to start counting seconds in the textbox.
我想按下 Button1 并开始在文本框中计算秒数。
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.
因此,我决定使用 stopWatch 类,因为它具有符合规范的高分辨率。
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.
但是根据我下面的 VB.NET 代码,在我看来,整个“dotnet 冒险”是不可能的。那是因为当我按下 Button1 时,整个表单会冻结,我无法按下 Button2 来停止计时器。
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
结束班
回答by Andreas
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 Button1is clicked, the Button1_Clickmethod is executed and no other event will be processed until it finishes. Since your design requires Button2.Clickto be processed in order to terminate the loop in Button1.Click, it will never terminate.
在 WinForms 中,有一个 UI 线程执行消息循环。基本上,每个事件都被添加到消息队列中,一个又一个事件被处理。当Button1被点击时,该Button1_Click方法被执行并且没有其他事件将被处理,直到它完成。由于您的设计需要Button2.Click进行处理才能终止 中的循环Button1.Click,因此它永远不会终止。
To correctly implement what you want, you'd have to start the stopwatch on Button1.Clickand put the UI update logic into the Tickevent of a timer which you place on the form.
要正确实现您想要的,您必须启动秒表Button1.Click并将 UI 更新逻辑放入Tick放置在表单上的计时器事件中。
回答by Idle_Mind
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.Elapsedproperty. All you need to do is update the GUI from a Timer.Tickevent. Basically the Timer just asks the Stopwatch what the current time is and displays it...no calculations needed.
您正在“浪费”时间,因为您正在手动添加时间跨度:enableTime = enableTime + TimeSpan.FromSeconds(1)。当您使用它的Stopwatch.Elapsed属性时, Stopwatch() 本身总是准确的。您需要做的就是从Timer.Tick事件更新 GUI 。基本上计时器只是询问秒表当前时间是什么并显示它......不需要计算。
The following will update ten times a second, will not "drift", and will not peg the CPU:
以下将每秒更新十次,不会“漂移”,也不会固定 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
回答by dbasnett
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

