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
參考文章:


沒有留言:
張貼留言