1

我今天在工作中遇到了一个让我感到困惑的情况,我在下面的代码中对其进行了简化。此代码在调试期间构建并且不会引发异常。

假设我有一个 WinForms 应用程序。在我的主 UI 线程中,我分离出另一个线程,该线程实例化一个对象,该对象又持有对控件的引用(在我的示例中为 label1)。然后我在我的对象 (SetLabelText) 上调用一个方法,如果需要,它会将其执行传递回 UI 线程。

让我感到困惑的是,当我们回到 UI 线程并执行 SetLabelText 时,当我们在未创建 Thing 实例的线程(即 UI 线程)上执行时,.net CLR 是否能够访问 labelText 变量。

public partial class Form1 : Form
{
    delegate void DoSomethingDelegate();

    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        var t = new Thread(DoSomethingWithThing);
        t.Start();
    }

    private void DoSomethingWithThing()
    {
        var thing = new Thing(this.label1);
        thing.SetLabelText();
    }
}

public class Thing
{
    private Label label;
    private string labelText = "new value";
    delegate void SetLabelTextDelegate();

    public Thing(Label label)
    {
        this.label = label;
    }

    public void SetLabelText()
    {
        if (this.label.InvokeRequired)
        {
            var setLabelDel = new SetLabelTextDelegate(SetLabelText);
            this.label.Invoke(setLabelDel);
        }
        else
        {
            this.label.Text = this.labelText;
        }
    }
}
4

1 回答 1

10

对对象的引用在任何线程上都可用。

线程之间没有沙盒。它们共享资源,除非您明确创建非共享资源。

线程是执行上下文。将您的应用程序视为厨房,将每个线程视为厨师。他们可以同时工作,但如果他们中的两个人试图同时使用同一把刀,事情就会变得一团糟。这就是为什么 c# 有lock关键字和其他同步机制的原因。

由于 WinForms 的呈现方式,WinForms 对控件的访问有限制。

于 2013-09-05T15:17:49.013 回答