簡體   English   中英

為什么 WPF 中的 UI 控件具有線程親和性?

[英]Why do UI Controls in WPF have Thread Affinity?

為什么創建控件的線程是可以更新它的線程? 為什么 MS 不讓人們能夠使用鎖定和其他線程同步技術來讀取和寫入具有多個線程的 UI 控件上的屬性。

每個 MSDN 的簡短描述是

WPF 的線程模型與具有線程關聯的單線程執行的現有 User32 線程模型保持同步。 這樣做的主要原因是互操作性——像 OLE 2.0、剪貼板和 Internet Explorer 這樣的系統都需要單線程關聯 (STA) 執行

更長的描述是這樣的:

WPF 中的大多數對象都源自 DispatcherObject,它提供了處理並發和線程的基本構造。 WPF 基於由調度程序實現的消息傳遞系統。 這很像熟悉的 Win32 消息泵; 實際上,WPF 調度程序使用 User32 消息來執行跨線程調用。

在討論 WPF 中的並發時,實際上有兩個核心概念需要理解——調度程序和線程關聯。

在 WPF 的設計階段,目標是轉移到單線程執行,但非線程“關聯”模型。 當組件使用執行線程的身份來存儲某種類型的狀態時,就會發生線程關聯。 最常見的形式是使用線程本地存儲 (TLS) 來存儲狀態。 線程親和性要求每個邏輯執行線程僅由操作系統中的一個物理線程擁有,這可能會占用大量內存。 最后,WPF 的線程模型與現有的具有線程親和性的單線程執行的 User32 線程模型保持同步。 這樣做的主要原因是互操作性——像 OLE 2.0、剪貼板和 Internet Explorer 這樣的系統都需要單線程關聯 (STA) 執行。

鑒於您擁有具有 STA 線程的對象,您需要一種在線程之間進行通信的方法,並驗證您是否在正確的線程上。 這就是調度員的作用。 調度器是一個基本的消息調度系統,具有多個優先級隊列。 消息的示例包括原始輸入通知(鼠標移動)、框架功能(布局)或用戶命令(執行此方法)。 通過從 DispatcherObject 派生,您可以創建一個具有 STA 行為的 CLR 對象,並將在創建時獲得一個指向調度程序的指針。

你可以在這里閱讀全文

我個人更喜歡 WPF 的單線程模型,而不是必須使用鎖定和線程同步技術。 Dispatcher可用於將消息傳遞到不同優先級的主 UI 線程,它負責處理大多數小型后台進程,如果您需要任何繁重的處理,那么您仍然可以為此創建自己的后台線程。

WPF 與幾乎所有 UI 工具包一樣,通過泵送消息循環來工作。 由於消息可以隨時出現並影響任何控制,因此您需要全局鎖定。 為了減少出錯的可能性,您可能需要一個函數來調用鎖下的委托。 也許是這樣的:

Dispatcher.Invoke(Delegate, Object())

這被編組到 UI 線程而不是獲取全局鎖的事實只是一個實現細節。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM