簡體   English   中英

你可以從另一個線程訪問UI元素嗎? (沒有設定)

[英]Can you access UI elements from another thread? (get not set)

我在google / here上看到很多線程在UPDATING來自另一個線程的UI元素。

如果我想獲得復選框的值,該怎么辦?

我能不做任何特別的事情嗎?

編輯 :似乎我必須收回我之前寫的內容。 嘗試以下方法:

添加了一個名為myTextBox的文本框,並嘗試檢索Text屬性的值:

Thread t = new Thread(
    o =>
    {
        Thread.Sleep(2000);                    
        string value = myTextBox.Text;
        Thread.Sleep(2000);
    });
t.Start();

似乎應用程序(WPF)在2秒后崩潰。 使用調度程序工作:

Thread t = new Thread(
    o =>
    {
        Thread.Sleep(2000);
        myTextBox.Dispatcher.BeginInvoke(
            (Action)(() => { string value = myTextBox.Text; }));
        Thread.Sleep(2000);
    });
t.Start();

因此,在從GUI組件讀取值時,您仍需要通過調度程序線程,至少在WPF中。

第二次編輯 :這會變得更好。 顯然重復經典WinForms的實驗表明,它可以在不使用Invoke/BeginInvoke情況下讀取Text屬性。 有趣的是,似乎也設置屬性工作正常(沒有調用),雖然我打賭它不是線程安全的,應用程序不會因為某些原因抱怨。

結論 :在任何情況下,在與來自其他線程的GUI組件交互時使用調度程序是個好主意,因為它確保將讀/寫序列化為單個線程,因此您沒有線程安全問題。

你可以從另一個線程訪問UI元素嗎? (沒設置)?

沒有。

這是交易。 UI元素具有非常嚴格的線程親和力要求。 這意味着您只能從托管它的線程訪問該元素。 這包括各種訪問,包括簡單的讀取。 1

它對於簡單的屬性獲取者可能工作正常,但其感知的安全性將是特定控制實現方式的偶然結果。 由於Control實例具有線程親和性,因此它們可能會使用線程本地存儲技術來保存它們的某些狀態,當然這些狀態與不同的線程不兼容。 或者,如果您嘗試閱讀的值處於半生不熟狀態,該怎么辦? 由於寫入可能發生在您無法控制的代碼中,因此無法同步對該讀取的訪問。 而且這仍然忽略了可能出現的微妙的記憶障礙問題。

再說一次,如果看起來有效,那就把它當成一個意外。 從一個線程訪問UI元素而不是托管它們的UI元素是一種災難。 事情可能會無法預測和驚人地失敗。


1 這條規則很少有例外。 使用ISynchronizeInvoke方法就是一個這樣的例外。

你可以但嚴格來說它不是線程安全的。 例如,如果屬性Get代碼包含多個操作,則UI線程可以在Get操作期間的中途行動,從而導致意外結果。

只需像平常一樣讀取值即可。 只有更新控件,才需要切換到GUI線程。

暫無
暫無

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

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