Demo效果
还是使用demo的形式来说下如何访问控件,先看下我们想要的效果
实现思路
任务1和任务2采用两个线程,将每次运算结果显示在lable中,我们先按自己的思路写下看能不能实现。
private void button1_Click(object sender, EventArgs e)
{
int a = 0;
Thread objThread1 = new Thread(delegate ()
{
for (int i = 1; i <= 20; i++)
{
a += i;
this.lblResult1.Text = a.ToString();
Thread.Sleep(500);
}
});
objThread1.IsBackground = true;//设置为后台线程(通常这样设置)
objThread1.Start();
}
private void button2_Click(object sender, EventArgs e)
{
int a = 0;
Thread objThread2 = new Thread(() =>
{
for (int i = 1; i <= 50; i++)
{
a += i;
this.lblResult2.Text = a.ToString();
Thread.Sleep(500);
}
});
objThread2.IsBackground = true;//设置为后台线程(通常这样设置)
objThread2.Start();
}
以上的代码是两个按钮点击事件中的内容,按我们的常规思路,每获得一个a值更改一次控件内容,但是我们运行这段代码会发现一个异常。
因为调用的控件在主线程生成,在其他线程调用时就会报以上的异常。下面我们通过invoke方法来解决。
修改点击事件中的方法:
解决方法
private void button1_Click(object sender, EventArgs e)
{
int a = 0;
Thread objThread1 = new Thread(delegate ()
{
for (int i = 1; i <= 20; i++)
{
a += i;
if (this.lblResult1.InvokeRequired)//判断是否调用Invoke方法
{
this.lblResult1.Invoke(new Action<string>(s => { this.lblResult1.Text = s; }), a.ToString());
}
Thread.Sleep(500);
}
});
objThread1.IsBackground = true;//设置为后台线程(通常这样设置)
objThread1.Start();
}
1.先行判断是否需要调用Invoke方法
if (this.lblResult1.InvokeRequired)
2.使用Invoke方法
his.lblResult1.Invoke(new Action<string>(s => { this.lblResult1.Text = s; }), a.ToString());
在Invoke方法中Invoke的第一个参数为一个委托,这里我简便使用了Action泛型委托实现,第二个参数是委托的入参。
通过如上的方法就可以解决跨线程访问控件。