今日の仕事で困惑する状況に出くわしました。これを次のコードで簡略化しました。このコードはビルドされ、デバッグ中に例外をスローしません。
WinForms アプリがあるとします。私のメイン UI スレッドでは、オブジェクトをインスタンス化する別のスレッドをスピンオフし、そのオブジェクトがコントロールへの参照を保持します (私の例では label1)。次に、必要に応じてその実行を UI スレッドに戻すオブジェクト (SetLabelText) のメソッドを呼び出します。
私が困惑したのは、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;
}
}
}