2010-08-19 31 views
1

我看到有很多關於線程修改窗​​體項目的問題;然而,我只想從線程讀取複選框(例如)的狀態。所以...關於線程窗體訪問開銷的問題

是否有任何額外的開銷來訪問窗體中的複選框的「檢查」狀態(從一個線程)-vs-創建一個布爾將反映該複選框的狀態,並有線程訪問布爾值呢?

回答

2

答案是最肯定是有的。原因是因爲正確訪問UI控件狀態涉及很多工作。您基本上必須將方法調用編組到UI線程才能正確訪問控件。編組操作需要通過包含委託引用的消息泵向UI線程發送消息。 UI線程最終會將其提取並執行。由於我從來沒有計時這一行動,我無法肯定地說這是多麼昂貴,但我懷疑這是一筆不小的時間。它必須這樣做,因爲UI控件具有線程關聯性。這意味着它們只能在創建它們的線程上訪問。要委派一名代表,請使用Control.InvokeControl.BeginInvoke方法。

Fredrik已經提到了避免編組操作的一個非常好的解決方法。這是它在代碼中的樣子。

public partial class YourForm : Form 
{ 
    // Make sure to mark this variable as volatile. 
    private volatile bool m_Checked; 

    private void YourForm_Load(object sender, EventArgs e) 
    { 
     m_Checked = YourCheckbox.Checked; 
     var thread = new Thread(
      () => 
      { 
       while (true) 
       { 
        // This read will come from main memory since the 
        // variable is marked as volatile. 
        bool value = m_Checked; 
       } 
      }); 
     thread.Start(); 
    } 

    private void YourCheckbox_CheckedChanged(object sender, EventArgs e) 
    { 
     // This write will be committed to main memory since the 
     // variable is marked as volatile. 
     m_Checked = YourCheckbox.Checked; 
    } 

} 
+0

好吧,我認爲這回答了我的問題,但我想確保我清楚...所以你說這樣的邏輯在線程內... if (checkbox_YADA.Checked) ... else ... 實際上下文切換到UI線程,檢索'Checked'bool的值,然後將該信息返回給調用線程?哎呀!如果情況確實如此,那麼通過線程訪問(甚至只讀)表單上的任何內容都是無效的。 請確認... 謝謝。 – 2010-08-19 18:12:07

+0

@Ed:不,切換到UI線程不是自動的。它必須通過'Control.Invoke'手動完成。剛剛描述的邏輯將繼續在工作線程中運行,事實上,大部分時間可能正常工作,特別是因爲CheckBox.Checked屬性只是讀取實例變量。但是,仍然會有內存障礙問題,如果該屬性更復雜,並且需要閱讀窗口句柄或其他東西,那麼所有地獄都可能崩潰,並且您的應用程序將無法預料地和驚人地失敗。 – 2010-08-19 18:29:51

3

無論線程問題如何,我都建議將值存儲在bool字段中; CheckBox應該是數據的可視表示,而不是數據本身。這將導致耦合代碼更少,而您決定更改UI的影響更小。

+0

@Ed,我也會非常小心地允許CheckBox在線程運行時主動監視它並更改bool字段的狀態。例如,如果您在監聽線程中監視真/假更改,那麼字段的狀態很可能會從第一個線程快速更改,而不會有監聽線程觀察到更改。 – 2010-08-19 15:05:12

+1

@丹·布萊恩特:但是接下來的問題是線程是否對狀態感興趣(在這種情況下,當閱讀時狀態良好,即使它錯過了一個改變)或者轉換中(在這種情況下,可以認爲一個XXXResetEvent是更合適的觀察對象) – 2010-08-19 16:22:23