关于线程表单访问开销的问题

时间:2010-08-19 14:11:56

标签: c# multithreading

我看到有很多关于线程修改表单中的项目的问题; 但是,我只是想从一个线程中读取一个复选框的状态(例如)。所以......

是否有任何额外的开销来访问表单中的复选框的“已检查”状态(来自线程)-vs-创建将反映该复选框状态的bool,并让线程访问布尔值而不是?

3 个答案:

答案 0 :(得分:3)

我建议将值存储在bool字段中,而不管线程问题如何; CheckBox应该是数据的直观表示,而不是数据本身。这将导致代码耦合较少,您决定更改UI的影响较小。

答案 1 :(得分:2)

线程无法访问任何表单UI元素,包括读取复选框的任何属性。必须仅从主UI线程调用Control方法和属性:

  

使用InvokeRequired   属性来同步访问   从多个线程控制。对于   有关多线程的更多信息   Windows窗体控件,请参阅How to: Make Thread-Safe Calls to Windows Forms Controls

答案 2 :(得分: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;
    }

}