第二個要談到的時間人就是System.Timers.Timer了,System.Timers.Timer和Windows.Forms.Timer有一些個不同點
第二個要談到的時間人就是System.Timers.Timer了,System.Timers.Timer和Windows.Forms.Timer有一些個不同點,簡單列幾個比較重要的如下:
(1)System.Timers.Timer的Interval屬性值的資料型別是Double;而在Windows.Forms.Timer中這個屬性植是Integer。
(2)System.Timers.Timer中引發的事件名稱為Elapsed;Windows.Forms.Timer則使用Tick事件。
(3)System.Timers.Timer使用背景執行緒來處理Elapsed事件所要處理的內容;Windows.Forms.Timer則是在UI執行緒,也就是表單畫面執行緒中處理Tick事件。
(4)當System.Timers.Timer的Elapsed事件程序內容要變更表單畫面控制項時,需使用委派的方式或透過SynchronizingObject 屬性封送來處理。
(5)System.Timers.Timer可藉由AutoReset屬性的設定決定是否要不斷的循環。
以下我們就拿個實際的例子來測試System.Timers.Timer的功能,畫面和三種時間人《.NET中的Timer(1)》差不多,就是多了個AutoRest的選項,先來看一下程式的內容:
Public Class Form1
Dim SystemTimer As New System.Timers.Timer
Dim iTickTimes As Integer = 1
Delegate Sub SetMsg1Callback(ByVal InputString As String)
Private Sub DisplayMsg1(ByVal strReceive As String)
Try
If Me.TB_S.InvokeRequired Then
Dim d As New SetMsg1Callback(AddressOf DisplayMsg1)
Me.Invoke(d, New Object() {strReceive})
Else
Me.TB_S.Text &= strReceive
End If
Catch ex As ObjectDisposedException
'停止的時候有可能會造成 ObjectDisposedException
'請參閱 [Try Catch能幫你做什麼(4)?] http://www.dotblogs.com.tw/billchung/archive/2009/04/04/7851.aspx
End Try
End Sub
Private Sub Btn_SysT_start_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Btn_SysT_start.Click
SystemTimer.Interval = NumericUpDown1.Value
SystemTimer.AutoReset = CheckBox1.Checked
'可以修改使用不同的Handler Method,觀察TextBox的內容是否有所不同
' AddHandler SystemTimer.Elapsed, AddressOf myTimerElapsed01 'Form timer Tick事件程序1
AddHandler SystemTimer.Elapsed, AddressOf myTimerElapsed02 'Form timer 用Tick事件程序2
TB_S.Text &= "Start:" & Environment.TickCount & vbCrLf
SystemTimer.Start()
End Sub
Private Sub BTN_SysT_stop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BTN_SysT_stop.Click
SystemTimer.Stop()
'RemoveHandler SystemTimer.Elapsed, AddressOf myTimerElapsed01 'Form timer Tick事件程序1
RemoveHandler SystemTimer.Elapsed, AddressOf myTimerElapsed02 'Form timer 用Tick事件程序2
TB_S.Text &= "Stop:" & Environment.TickCount & vbCrLf
End Sub
Private Sub BTN_Clear_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BTN_Clear.Click
TB_S.Clear()
iTickTimes = 1
End Sub
Private Sub myTimerElapsed01(ByVal sender As System.Object, ByVal e As System.Timers.ElapsedEventArgs)
DisplayMsg1("#" & iTickTimes & " Tick Begin:" & Environment.TickCount & vbCrLf)
Looping()
DisplayMsg1("#" & iTickTimes & " Tick End:" & Environment.TickCount & vbCrLf)
iTickTimes += 1
End Sub
Private Sub myTimerElapsed02(ByVal sender As System.Object, ByVal e As System.Timers.ElapsedEventArgs)
Dim imyTicks As Integer
imyTicks = iTickTimes
iTickTimes += 1
DisplayMsg1("#" & imyTicks & " Tick Begin:" & Environment.TickCount & vbCrLf)
Looping()
DisplayMsg1("#" & imyTicks & " Tick End:" & Environment.TickCount & vbCrLf)
End Sub
Private Sub Looping()
Dim i As Integer
'可以修改迴圈數,觀察程式的變化
For i = 0 To 1
System.Threading.Thread.Sleep(1)
Next
End Sub
End Class
來看看執行的結果 ,可以發現它在Elapsed事件中要處理的程序時間超過Interval屬性值也不怎麼乖巧,不過和Windows.Forms.Timer有一個不同點是,它會把事情做完,但同一件事可能會做好多次,可以從圖上看的出來有些程序還沒End,下一個程序就Begin了。而且完成的順序也會出現混亂的狀況。
接下來一樣把間隔時間改為100,果然執行結果就正常的許多,順便觀察一下時間的差異,準確度其實和之前的Windows.Forms.Timer差不多,也許要做很大量的數據才能比較出差異吧。
來看一下AutoReset,當我們將AutoReset屬性設為False時,可以發現Elapsed事件僅僅被執行了一次,在這種狀況下,若要再次執行必須再呼叫一次SystemTimer.Start() 方法。這個範例程式是以VB2005撰寫的,可以在以下超連結下載SysTimerTest.rar。
最後談一下如何使用SynchronizingObject 屬性,這個屬性會使得System.Timers.Timer處理Elapsed事件所要處理的內容之時產生與Windows.Forms.Timer處理Tick事件類似的結果,也就是當System.Timers.Timer執行個體設定了SynchronizingObject 屬性之後,它會和此屬性所指向的物件在相同的執行緒上引發Elapsed事件。以下是一個簡單的設定例子:
Private Sub Btn_SysT_start_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Btn_SysT_start.Click
SystemTimer.Interval = NumericUpDown1.Value
SystemTimer.AutoReset = CheckBox1.Checked
SystemTimer.SynchronizingObject = Me
'可以修改使用不同的Handler Method,觀察TextBox的內容是否有所不同
' AddHandler SystemTimer.Elapsed, AddressOf myTimerElapsed01 'Form timer Tick事件程序1
AddHandler SystemTimer.Elapsed, AddressOf myTimerElapsed03 'Form timer 用Tick事件程序2
TB_S.Text &= "Start:" & Environment.TickCount & vbCrLf
SystemTimer.Start()
End Sub
Private Sub myTimerElapsed03(ByVal sender As System.Object, ByVal e As System.Timers.ElapsedEventArgs)
' 使用 SynchronizingObject 這邊就沒使用委派了
TB_S.Text &= "#" & iTickTimes & " Tick Begin:" & Environment.TickCount & vbCrLf
Looping()
TB_S.Text &= "#" & iTickTimes & " Tick End:" & Environment.TickCount & vbCrLf
iTickTimes += 1
End Sub