2019年7月5日 星期五

SYSTEM.WINDOWS.FORMS.TIMER與SYSTEM.TIMERS.TIMER的區別


SYSTEM.WINDOWS.FORMS.TIMERSYSTEM.TIMERS.TIMER的區別
.NET Framework裡面提供了三種Timer

System.Windows.Forms.Timer
System.Timers.Timer
System.Threading.Timer
VS.Net 2005預設只有一個Timer控制項,但那是System.Forms.Timer控制項。如果要使用System.Timers.Timer的控制項,需要在工具箱上按一下右鍵,手動添加的步驟:工具箱按一下右鍵->Add Item->找到命名空間是System.Timers.Timer的控制項,將其選中,OK即可。

這裡簡單的介紹一下這兩種Timer的區別。

System.Windows.Forms.Timer是使用得比較多的TimerTimer Start之後定時(按設定的Interval)調用掛接在Tick事件上的EventHandler。在這種TimerEventHandler中可以直接獲取和修改UI元素而不會出現問題,因為這種Timer實際上就是在UI執行緒自身上進行調用的。也正是因為這個原因,導致了在TimerEventHandler裡面進行長時間的阻塞調用,將會阻塞介面回應的後果。下面是一個簡單的例子:
Timer timer1 = new Timer();
private void Form1_Load(object sender, EventArgs e)
{
    timer1.Interval = 3000;
    timer1.Tick += delegate(object o, EventArgs args)
    {
        DoWork();
    };
    timer1.Start();
}
private void DoWork()
{
    for (int i = 0; i < 10; i++)
    {
        System.Threading.Thread.Sleep(1000);
    }
}
在這個例子中,DoWork方法裡面將會阻塞10秒,在這10秒之內,UI將會失去回應。而通過使用System.Timers.Timer,就可以解決這個問題。因為System.Timers.Timer是在.NETThread Pool上面運行的,而不是直接在UI Thread上面運行,所以在這種TimerEventHandler裡面進行耗時較長的計算不會導致UI失去回應。

但是這裡有兩個地方需要注意:

一、因為一般來說System.Timers.Timer不是運行在UI Thread上面的,所以如果要在這種TimerEventHandler裡面更新UI元素的話,需要進行一次執行緒切換,在WinForm開發中一般通過UI元素的Invoke方法完成:

private void DoWork()
{
    for (int i = 0; i < 10; i++)
    {
        System.Threading.Thread.Sleep(1000);
    }
    this.Invoke(new UpdateUICallBack(UpdateUI));
}
private delegate void UpdateUICallBack();
private void UpdateUI()
{
}
二、System.Timers.Timer有一個PropertySynchronizingObject 。如果設置了這個Property(一般是某個Form),那麼之後對Timer掛接的EventHandler的調用將會在創建這個UI元素的執行緒上進 行(一般來說就是UI執行緒)。值得注意的是,如果你通過WinForm設計器把System.Timers.Timer拖放到Form上,那麼這個 Property將會自動被設置。此時這種Timer就和System.Windows.Forms.Timer的效果一樣:長調用將會阻塞介面。

總結:

System.Windows.Forms.Timer

1. 它是一個基於Form的計時器
2. 創建之後,你可以使用Interval設置Tick之間的跨度,用委託(delegatehook Tick事件
3. 調用StartStop方法,開始和停止
4. 完全基於UI執行緒,因此部分UI相關的操作會在這個計時器內進行
5. 長時間的UI操作可能導致部分Tick丟失

System.Timers.Timer

1. 用的不是Tick事件,而是Elapsed事件
2. System.Windows.Forms.Timer一樣,用StartStop方法
3. AutoReset屬性決定計時器是不是要發起一次事件然後停止,還是進入開始/等待的迴圈。System.Windows.Forms.Timer沒有這個屬性
4. 設置對於UI控制項的同步物件(synchronizing object),對控制項的UI執行緒發起事件

System.Windows.Forms.Timer 是對於使用者介面程式設計的比較顯然的選擇。而另外兩個之間的選擇就不是很明顯。如果必須在IContainer內,那麼就應該選擇 System.Timers.Timer。如果沒有用到System.Timers.Timer的特性,那麼建議選擇 System.Threading.Timer,因為它稍稍羽量級一些。

Timer 是先等待再執行,如果我們要達到先執行再等待的效果,設置 默認時間間隔Interval =100,或者更少為1(不能為0),之後再引發事件內更改 時間間隔Interval 為想要的值。

轉載自:http://www.cnblogs.com/lonelyxmas/archive/2009/10/27/1590604.html

沒有留言:

張貼留言