我遇到了一种情况,使今天的工作感到困惑,在下面的代码中我对此进行了简化。该代码在调试过程中会生成并且不会引发任何异常。
假设我有一个WinForms应用程序。在我的主UI线程中,我产生了另一个线程,该线程实例化了一个对象,该对象又持有对控件的引用(在我的示例中为label1)。然后,我在对象(SetLabelText)上调用一个方法,如果需要,该方法将其执行返回给UI线程。
让我感到困扰的是,当我们在未创建Thing实例的线程(即UI线程)上执行时,当我们回到UI线程并执行SetLabelText时,.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;
}
}
}
对对象的引用在任何线程上都可用。
线程彼此之间没有沙盒。它们共享资源,除非您显式创建非共享资源。
线程是执行上下文。将您的应用程序视为厨房,将每个线程视为厨师。它们可以同时工作,但是如果其中两个试图同时使用同一把刀,事情就会变得困惑。这就是为什么C#具有lock
关键字和其他同步机制的原因。
由于WinForms呈现的方式,WinForms对控件的访问有限制。
我是一名优秀的程序员,十分优秀!