三種時間人《.NET中的Timer(2)》

第二個要談到的時間人就是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 ClassSysTimer1

   

       來看看執行的結果 ,可以發現它在Elapsed事件中要處理的程序時間超過Interval屬性值也不怎麼乖巧,不過和Windows.Forms.Timer有一個不同點是,它會把事情做完,但同一件事可能會做好多次,可以從圖上看的出來有些程序還沒End,下一個程序就Begin了。而且完成的順序也會出現混亂的狀況。

 

 

 

 

 

 

 

 

  SysTimer2 

       接下來一樣把間隔時間改為100,果然執行結果就正常的許多,順便觀察一下時間的差異,準確度其實和之前的Windows.Forms.Timer差不多,也許要做很大量的數據才能比較出差異吧。

     

 

 

 

 

 

 

 

 

 

   SysTimer3

 

 

       來看一下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