关键字:CheckForIllegalCrossThreadCalls、委托、new Action
适用场景
当我们进行Winform开发时,会出现这样一种情况:我们在代码中开启了一个线程,在线程中我们想要获取到界面上的值,亦或是我们想要在线程中给界面上的控件赋值,此时就会出现如下图所示的错误:System.InvalidOperationException:“线程间操作无效: 从不是创建控件“xxx”的线程访问它。”

这时,有三种写法可以实现跨线程的赋值。
方法一:关闭对错误线程调用的捕获
使用代码如下
public Form1()
{
InitializeComponent();
//^.^增加此行关闭对错误线程调用的捕获
Control.CheckForIllegalCrossThreadCalls = false;
}
只要在窗体的构造方法中将捕获关闭即可实现跨线程调用不报错,此行代码的添加位置不仅可以在构造方法中,一般来说,只要添加在跨线程调用的代码之前都能起作用。
方法二:使用委托
- 为什么要使用委托的方式?
跨线程调用报错的原因是我们在在非 UI 线程中对 UI 控件进行了操作,而在C#中, UI 控件不是线程安全的,只能在创建它们的线程(即 UI 线程)上进行访问和修改。此时,我们可以通过this.Invoke(委托实例)的方式将委托传递给 UI 线程的消息队列,UI 线程会在合适的时机从消息队列中取出该委托并执行。
- 如何实现?
现在假设有一个应用场景:窗体中有一个label标签(其中的Text值为0),有一个按钮控件。
需要实现:点击按钮控件,按钮控件点击事件中开启一个线程。在线程中循环修改label标签的值,使label标签计数,每秒增加+1。

完整代码如下。
public partial class Form1 : Form
{
int count = 0;
//第一步:定义委托类
public delegate void SetTextDelegate(string value);
//第二步:定义委托方法
public void SetText(string value)
{
label1.Text = value;
}
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Thread th = new Thread(LabelAddFunc);
th.Start();
}
//线程方法
public void LabelAddFunc()
{
while (true) {
count++;
//第三步:实例化委托类对象
SetTextDelegate setText = new SetTextDelegate(SetText);
//第四步:调用委托实现跨线程修改label的值
this.Invoke(setText, count.ToString());
Thread.Sleep(1000);//睡眠1s,每秒label值+1
}
}
}
核心重点就是this.Invoke(setText, count.ToString());
其中,Invoke的第一个参数是委托的方法,第二个参数是委托方法的输入参数。
这种方法在使用时要写很多代码,非常不方便,那么,有没有更简便的写法呢?有的,就是下面要介绍的第三种方式。
方法三:new Action
方法三在本质上还是用了委托,因为C#帮我们内置了Action委托和Func委托,其中Action是无参数的,Func是有参数的。那么我们可以使用Action来简化方法二的代码。这就是方法三的实现。
public partial class Form1 : Form
{
int count = 0;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Thread th = new Thread(LabelAddFunc);
th.Start();
}
//线程方法
public void LabelAddFunc()
{
while (true) {
count++;
//====使用C#预定义委托===
this.Invoke(new Action(() =>
{
label1.Text = count.ToString();
}));
//========================
Thread.Sleep(1000);//睡眠1s,每秒label值+1
}
}
}
综上,这就是三种跨线程调用的解决方法,希望对各位小伙伴有帮助,如果您发现了错漏或有更好的实现,欢迎评论区交流^. ^
7789



被折叠的 条评论
为什么被折叠?



