多线程总结之旅(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):跨线程调用控件的几种方式的主要内容,如果未能解决你的问题,请参考以下文章

并发编程实现多线程的几种方式

java实现同步的几种方式(总结)

Java创建线程的几种方式

Java创建线程的几种方式

Java创建线程的几种方式

Java创建线程的几种方式