WPF 執行緒:
在WPF應用程式中主要有兩個執行緒(Thread):Rendering Thread和UI Thread
- Rendering Thread: 在背景中執行並協助UI Thread完成工作
- UI Thread: 主要負責處理Input、Event與程式碼的部分
在WPF中, 所有UI工作和事件都是在UI Thread上完成. 每個WPF程式至少有一個Dispatcher物件和一個UI Thread. 而大部分WPF物件的操作都是binding在UI Thread上,其他的Thread如果想要直接操作這些UI物件, 是不被允許的, 因為只有建立 DispatcherObject 的Thread才可以存取UI物件。例如, 要讓其他的Thread存取 Label 的 Content 屬性, 將會發生錯誤, 此範例如下所示:
設計一個WPF視窗, 當按下Button後, 讓Label顯示按Button的次數.
C#程式碼如下所示:
C#程式碼如下所示:
private static int _clickCount = 0; private void btnShowText_Click(object sender, RoutedEventArgs e) { _clickCount++; // Update Label Conten in another thread Thread updateThread = new Thread(UpdateText); updateThread.Start(); } private void UpdateText() { labelClickCount.Content = "Click Count= " + _clickCount.ToString(); }
[圖1]無法再另一個Thread中更新UI
Dispatcher可讓其他的Thread在WPF中的 UI Thread上執行程式碼. Dispatcher又被稱為WPF中的Message Pump,提供一個機制去發送工作項目給UI Thread進行處理.
當Dispatcher將工作項目轉給UI Thread時, 會讓UI Thread進入封鎖狀態(畫面鎖定, 因為要處理工作項目). 其他的Thread必須將工作委派給與 UI Thread相關聯的 Dispatcher. 這可以使用 Invoke 或 BeginInvoke 完成.
- Invoke 是同步呼叫,也就是說,除非 UI 執行緒實際完成委派的執行,否則不會返回.
- BeginInvoke 是非同步的,會立即返回.
下面的程式碼, 將說明其解決方法:
C#程式碼如下所示:
private static int _clickCount = 0; // Declare a delegate type for updating UI private delegate void UpdateDelegate(int number, string str); private void btnShowText_Click(object sender, RoutedEventArgs e) { _clickCount++; Thread updateThread = new Thread(UpdateText); updateThread.Start(); } private void UpdateText() { //labelClickCount.Content = "Click Count= " + _clickCount.ToString(); // Places the delegate onto the UI Thread's Dispatcher Dispatcher.Invoke(new UpdateDelegate(UpdateClickCountAction), _clickCount, "Click Count = "); } private void UpdateClickCountAction(int number, string str) { labelClickCount.Content = str + number.ToString(); }
[圖2] 利用Dispatcher執行另一個Thread的function
參考文章:
沒有留言:
張貼留言