2013-05-11 92 views
3

我想創建一個簡單的定時器使用VB.NET秒錶循環使用VB.NET

enter image description here

我想按Button1的,並開始在文本框中秒計數,這個接口。

I do not want to use the Timer Component because it does not offer high resolution.

所以,我按規格決定使用秒錶類,由於其較高的分辨率。

但根據我的VB.NET代碼,在我看來,整個「dotnet冒險」是不可能的。這是因爲當我按下Button1時,整個窗體凍結,我不能按Button2來停止計時器。

我的代碼有什麼問題嗎? 我應該怎麼做才能具備上述功能?

在此先感謝!

 
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

末級

+0

即使可以找出線程和UI更新,您仍然不會獲得所需的分辨率。看看你是如何檢查'stopWatch.ElapsedTicks.Equals(TimeSpan.TicksPerSecond)'?這可能永遠不會是真的。當你的循環正在運行時,這些滴答滴答會從你的下面滑出 - 你不會看到它們全部。即使你做了,當你重新啓動計時器時,你將失去更多的分辨率。漂移是不可避免的。這不是.NET的問題,它是計算機的基本功能(至少是你使用的)。 – 2013-05-11 11:59:33

+0

在我自己的觀點,我與主要概念錯過分辨率以上納秒的極少數這樣的分辨率是儘可能好。但我承認我可能是錯的! – Novemberland 2013-05-11 12:05:28

+0

你想要的分辨率是什麼?難道你只是不會'錯過'一秒鐘,就像這個人在關聯問題中所做的那樣?或者你真的需要一堆小數位嗎? – 2013-05-11 12:08:28

回答

4

Winforms中,有執行所述消息循環一個UI線程。基本上,每個事件都會被添加到消息隊列中,並被處理,一個接一個的事件。當單擊Button1時,將執行Button1_Click方法,直到完成後纔會處理其他事件。由於您的設計需要處理Button2.Click以終止Button1.Click中的循環,因此它不會終止。

要正確實現你想要的,你必須在Button1.Click上啓動秒錶,並將UI更新邏輯放入您放置在窗體上的計時器的Tick事件中。

+0

+1好的答案。簡潔而準確,內容翔實。我不能說得這麼好。 – 2013-05-11 11:09:24

+0

@Andreas是否可以創建一個新的線程來應對所需的功能?我寧願開始學習如何使用.NET的線程,而不必使用Timer類! – Novemberland 2013-05-11 11:22:52

+1

當然這是可能的,但在這種情況下它沒有任何意義。事實上,這裏沒有任何線程可以實際做到。也許你認爲線程可以處理UI更新,但這是不允許的,因爲只有UI線程才能更新UI。如果你在另一個線程中進行UI更新,你必須在Form對象上使用Invoke,它只是將更新推送到UI線程的消息隊列中(正是Timer所做的)。 @StevenDoggart謝謝,別人顯然不喜歡我的回答:) – Andreas 2013-05-11 11:32:56

4

由於您正在手動添加時間範圍,因此您「失去」時間:enableTime = enableTime + TimeSpan.FromSeconds(1)。秒錶()本身始終準確,當您使用其Stopwatch.Elapsed屬性。您只需從Timer.Tick事件更新GUI即可。基本上,計時器只是詢問秒錶什麼是當前時間,並顯示它......不需要計算。

下面將更新的第二十次,不會「漂移」,並且將不釘住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 
1

一個實驗表明,計時器不應該被用於定時。使用計時器定期顯示秒錶經過時間是很好的。

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