WPF 採用單一 UI 執行緒模型,所有 UI 操作必須在建立控制項的執行緒 (UI 執行緒) 上進行。每個 UI 執行緒關聯唯一 Dispatcher 物件,負責依優先序調度工作項隊列。
public sealed class Dispatcher
{
[SecurityCritical, UIPermission(SecurityAction.LinkDemand, Unrestricted=true)]
public static void Run()
{
PushFrame(new DispatcherFrame());
}
}
Application.Run() 實為 Dispatcher.Run() 間接呼叫,啟動訊息迴圈 (DispatcherFrame)。DispatcherFrame 可巢狀,透過 Continue 屬性控制迴圈持續。Dispatcher.ExitAllFrames() 可終止所有框架 (不建議常規使用)。
WPF 絕大多數控制項繼承自 DispatcherObject (含 Application),具備**執行緒親和性**:只有擁有其 Dispatcher 的執行緒能直接存取。
private void button1_Click(object sender, RoutedEventArgs e)
{
new Thread(() => this.label1.Content = DateTime.Now.ToString()).Start();
}

private void button1_Click(object sender, RoutedEventArgs e)
{
new Thread(() =>
{
this.Dispatcher.Invoke(DispatcherPriority.Normal,
new Action(() => this.label1.Content = DateTime.Now.ToString()));
}).Start();
}
DispatcherPriority.Normal:優先序等級Action 委派:要在 UI 執行緒執行的程式碼類庫專案可用 Application.Current.Dispatcher.Invoke(...),指向同一 UI Dispatcher。
private void button1_Click(object sender, RoutedEventArgs e)
{
new Thread(() =>
{
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
new Action(() =>
{
Thread.Sleep(3000);
this.label1.Content = DateTime.Now.ToString();
}));
MessageBox.Show("Hi!"); // 非同步不阻塞背景執行緒
}).Start();
}
BeginInvoke 將工作項排入隊列立即返回,背景執行緒繼續執行;UI 執行緒稍後依優先序處理。
Freezable 間接繼承 DispatcherObject,但當從「可修改狀態」轉為「凍結狀態」 (Freeze()) 後,成為**自由執行緒物件**,失去執行緒親和性,可在任何執行緒安全存取。
Brush、Geometry、Transform、AnimationTimeline 等Freezable 文件