C#【委托/事件篇】跨线程访问窗体控件的方法

一、直接调用方法,方法中使用委托【textBox1.InvokeRequired】

using System;
using System.Windows.Forms;
using System.Threading;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        public Thread th = null;

        private void button1_Click(object sender, EventArgs e)
        {
            th = new Thread(Start);
            th.IsBackground = true;
            th.Start();
         
        }

        private void Start()
        {
            AddStr("111");
            UpdateText4("222");

            if (th != null)
            {
                th.Abort();
            }
        }

        //方法一:TextBox1的委托
        delegate void AddDg(string str);        //声明一个委托
        private void AddStr(string str)
        {
            if (textBox1.InvokeRequired)
            {
                AddDg dg = new AddDg(AddStr);
                textBox1.Invoke(dg, str);
            }
            else
            {
                textBox1.Text += str;
            }
        }

        //方法二:TextBox2的委托
        private void UpdateText4(object str)
        {
            if (textBox2.InvokeRequired)
            {
                // 当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想访问它
                Action<string> actionDelegate = (x) => { this.textBox2.Text += x.ToString(); };     //Lambda表达式的应用                                                                                                      
                //Action<string> actionDelegate = delegate (string txt) { this.textBox3.Text += txt; }; // 或者
                this.textBox2.Invoke(actionDelegate, str);
            }
            else
            {
                this.textBox2.Text += str.ToString();
            }
        }
    }
}

在这里插入图片描述

二、调用委托,委托进一步关联方法

1.使用委托【最基础的调用方法:委托五步法】

委托五步法:创建委托、声明委托、创建委托方法、委托绑定、调用委托

using System;
using System.Windows.Forms;
using System.Threading;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        //【01】声明委托
        public delegate void SetFormTextDelegate();
        //【02】创建委托对象
        private SetFormTextDelegate SetFormText;
        //【03】委托关联的方法
        private void ExcuteMethod()
        {
            textBox1.Text = "跨线程调用控件成功";
        }
        public Form1()
        {
            InitializeComponent();
            //【04】委托绑定
            this.SetFormText = ExcuteMethod;
        }
        public Thread th = null;

        private void button1_Click(object sender, EventArgs e)
        {
            th = new Thread(Start);
            th.IsBackground = true;
            th.Start();
         
        }

        private void Start()
        {
            //错误调用委托【报错:System.InvalidOperationException:“线程间操作无效: 从不是创建控件“Form1”的线程访问它。”】
            //因为想要在多线程里操作主线程的控件,你还得经过控件的同意【使用.Invoke()方法】
            //SetFormText();

            //【05】正确调用委托
            this.Invoke(SetFormText);
        }
    }
}

在这里插入图片描述
控件的父类Control提供了下边的方法:
在这里插入图片描述

2.使用Action作为委托来创建

微软从某个版本开始,出来了Action和Lamda表达式,Action是系统委托,也就是说,不需要我们手动创建委托了,它有个兄弟叫Func。

Action没有返回值,最多可以有16个参数。
Func必须要有返回值,最多可以有16个参数,最后一个参数表示返回值。

1)第一步简化:用Action作为委托来创建

		/// <summary>
        /// 多线程方法
        /// </summary>
        private void Start()
        {
            //【01】创建委托、绑定委托
            Action action = new Action(ExcuteMethod);
            //【02】调用委托
            this.Invoke(action);
        }

        //委托关联的方法
        private void ExcuteMethod()
        {
            textBox1.Text = "跨线程调用控件成功";
        }

2)第二步简化:委托对象只用一次,所以可以直接放到参数里

		/// <summary>
        /// 多线程方法
        /// </summary>
        private void Start()
        {
            //【01】创建委托、绑定委托、调用委托
            this.Invoke(new Action(ExcuteMethod));
        }

        //委托关联的方法
        private void ExcuteMethod()
        {
            textBox1.Text = "跨线程调用控件成功";
        }

3)第三步简化:用Lamda表达式代替方法【推荐使用!!!】

 		/// <summary>
        /// 多线程方法
        /// </summary>
        private void Start()
        {
            //【01】创建委托、绑定委托、调用委托
            this.Invoke(new Action(()=>
            {
                textBox1.Text = "跨线程调用控件成功";
            }));
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ElecNoon

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值