多线程总结之旅(112):跨线程调用控件的几种方式
Posted 搬砖滴
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程总结之旅(112):跨线程调用控件的几种方式相关的知识,希望对你有一定的参考价值。
本来是写完线程池就结束多线程总结之旅系列的,但是想想平时在项目中用到线程仅仅不够的,为什么这么说呢?举个例子:我们有一个函数,它的功能就是加载数据,然后绑定到datagridview。现在我们开启一个线程去执行这个函数。结果可想而知,它会报错:提示线程无法访问。。。之类的话。为什么报错呢?因为你在开启的线程中操作了datagridview控件,也就是你跨线程调用控件了。
那么我们应该怎么跨线程调用控件呢?下面我就把我总结的几种方法奉献给各位。
跨线程调用控件的几种方法:
1、方法一:Control.CheckForIllegalCrossThreadCalls = false;这是通过禁止编译器检查对跨线程访问操作,但是这种方法不是安全的解决办法,尽量不要使用。
为什么说不安全呢?
(1)我们查看CheckForIllegalCrossThreadCalls 这个属性的定义,就会发现它是一个static的,也就是说无论我们在项目的什么地方修改了这个值,他就会在全局起作用。
(2)一般对于跨线程访问是否存在异常,我们通常都会去检查。如果项目中其他人修改了这个属性,那么我们的方案就失败了。
代码下载:
2、方法二: 使用Delegate和Invoke跨线程调用控件(也叫代理方式)
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { Thread t = new Thread(ModifyLabelText); t.Start(); } /// <summary> /// 定义委托 /// </summary> private delegate void InvokeDelegate(); /// <summary> /// this.label1.InvokeRequired就是问问我们要不要使用代理执行ModifyLabelText方法 /// </summary> private void ModifyLabelText() { //使用Invoke代理的方式调用ModifyLabelText方法 if (this.label1.InvokeRequired) { InvokeDelegate invokeDelegate=new InvokeDelegate(ModifyLabelText); this.Invoke(invokeDelegate); } else { this.label1.Text = "我已经跨线程修改了Label的值"; } } } }
3、方法三:使用BeginInvoke和Delegate的方式。(也叫代理方式)
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { Thread t = new Thread(ModifyLabelText); t.Start(); } /// <summary> /// 定义委托 /// </summary> private delegate void InvokeDelegate(); /// <summary> /// this.label1.InvokeRequired就是问问我们要不要使用代理执行ModifyLabelText方法 /// </summary> private void ModifyLabelText() { //使用BeginInvoke代理的方式调用ModifyLabelText方法 if (this.label1.InvokeRequired) { InvokeDelegate invokeDelegate=new InvokeDelegate(ModifyLabelText); this.BeginInvoke(invokeDelegate); } else { this.label1.Text = "我已经跨线程修改了Label的值"; } } } }
在这里进行一下说明:
以上是关于多线程总结之旅(112):跨线程调用控件的几种方式的主要内容,如果未能解决你的问题,请参考以下文章