WPF 控制項繼承自 DispatcherObject,不再有 WinForms 的 InvokeRequired 與 Invoke/BeginInvoke。直接在背景執行緒存取 UI 屬性將拋出:
「呼叫執行緒無法存取這個物件,因為不同執行緒擁有它。」
| WinForms | WPF | 說明 |
|---|---|---|
Control.InvokeRequired | DispatcherObject.CheckAccess() | 回傳 bool,true 表示同執行緒可直接存取 |
Control.VerifyAccess() | DispatcherObject.VerifyAccess() | 非同執行緒拋出例外,用於防禦性程式設計 |
Control.Invoke/BeginInvoke | Dispatcher.BeginInvoke/Invoke | 將委派排入 UI 執行緒 Dispatcher 隊列 |
private void TryToUpdateButton(object uiObject)
{
Button btn = uiObject as Button;
if (btn == null) return;
// 檢查是否為 UI 執行緒
if (btn.CheckAccess())
{
UpdateButtonUI(btn); // 同執行緒,直接更新
}
else
{
// 非 UI 執行緒,排入 Dispatcher
btn.Dispatcher.BeginInvoke(
DispatcherPriority.Normal,
new Action<Button>(UpdateButtonUI),
btn);
}
}
private void UpdateButtonUI(Button btn)
{
btn.Content = "Updated at " + DateTime.Now.ToLongTimeString();
btn.Background = Brushes.LightGreen;
}
string result = (string)btn.Dispatcher.Invoke(
DispatcherPriority.Normal,
new Func<Button, string>(GetButtonText),
btn);
await btn.Dispatcher.InvokeAsync(() => {
btn.Content = "Async updated";
});
DispatcherPriority.Send:最高,立即處理 (慎用)DispatcherPriority.Normal:預設,適合大多數 UI 更新DispatcherPriority.Background:低優先級,適合非關鍵重繪async/await 或 Task 串聯DispatcherPriority.Background 分批處理,保持 UI 回應WeakReference