2009/07/07

在 WPF Application 中使用 Timer

一般來說在 Windows Forms 程式可以使用工具箱的 Timer (System.Windows.Forms) 來進行,另外也有更為精確的 System.Timers.Timer 可以用。但是在 Windows Presentation Foundation 應用程式中,沒有辦法使用 System.Windows.Forms.Timer,而 System.Timers.Timer 雖然仍可以使用,但是在時間觸發的事件中如果你去修改 UI 控制項的文字等等,會警告你只有擁有 UI 控制項的執行緒可以修改屬性。要解決這個方法可以用 Delegate 委派方法,但是這是 C# 的新玩意,Java沒有這種東西,所以不太懂。另一個方法是設定 Timer 的 SynchronizingObject 屬性,讓這個獨立的執行緒跟 UI 執行緒屬於同一個,但是 WPF 程式的頂層 Window 沒有實作 ISynchronizeInvoke 介面的樣子,所以無法使用。

System.Windows.Forms.Timer:
Windows Forms 程式用
計時執行緒跟 UI 執行緒是同一個 (或者說根本只有一個執行緒)
可能造成主畫面沒有反應的狀況 (因為相同執行緒的關係)

System.Timers.Timer:
所有 .NET 程式皆可使用
計時執行緒跟 UI 執行緒是不同個 (因此有執行緒同步問題)
不會造成主畫面沒有反應的情況


於是拜 Google 大神,得到了 System.Windows.Threading.DispatcherTimer 這個物件,可以用在 WPF 程式上,而且它所產生的執行緒跟擁有 UI 的執行緒是同一個,就不必擔心無法修改的問題。

private void btnTimer_Click(object sender, RoutedEventArgs e) {
// 設定 Timer 以自動讀取
DispatcherTimer t = new DispatcherTimer();
t.Tick += new EventHandler(t_Elapsed);
t.Interval = new TimeSpan(1000000);
t.Start();
}

private void t_Elapsed(object sender, EventArgs e) {
// ... do something...
}


值得注意的是 TimeSpan 建構元接受的數字是 100 奈秒單位,上面的 1000000 為 100 毫秒的意思。

System.Windows.Threading.DispatcherTimer:
所有 .NET 程式皆可使用
計時執行緒位於 Dispatcher 佇列之中,可以存取 UI 控制項
不會造成主畫面沒有反應的情況 (未測試,可能是因為統一由 Dispatcher 管理)

沒有留言:

張貼留言