首页 > 代码库 > 多线程总结之旅(112):跨线程调用控件的几种方式

多线程总结之旅(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):跨线程调用控件的几种方式