winform跨线程访问控件

net 原则上禁止跨线程访问控件,因为这样可能造成错误的发生,有一种方法是禁止编译器对跨线程访问作检查,Control.CheckForIllegalCrossThreadCalls = false;可以实现访问,但是出不出错不敢保证C#跨线程访问控件运行时错误,使用MethodInvoker即可解决。

C#中的Invoke方法主要用于在多线程环境下跨线程调用控件方法或者委托。它的作用是确保方法在正确的线程上执行,避免出现线程安全问题。

在访问控件是先判断控件的InvokeRequired属性,如果为true,则需要使用Invoke方法;如果为false,则可以直接调用方法。

在需要跨线程调用的地方,使用Invoke方法来执行指定的委托。

csharp 复制代码
        delegateShowMsg ShowSendMsg;
        Action<Byte[]> ShowReceiveMsg;

        private void frmMain_Load(object sender, EventArgs e)
        {
            ShowSendMsg = new delegateShowMsg(SendMsg_Show);
            ShowReceiveMsg = new Action<byte[]>(ReceiveMsg_Show);
        }



        /// <summary>
        /// 发送内容显示
        /// </summary>
        /// <param name="buf"></param>
        private void SendMsg_Show(Byte[] buf)
        {
            if (txtSendMsg.InvokeRequired)
            {
                // 当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想访问它
                this.txtSendMsg.Invoke(ShowSendMsg, buf);
            }
            else
            {
                this.txtSendMsg.Text += Change16ToStr(buf);
            }
        }

        /// <summary>
        /// 接收内容显示
        /// </summary>
        /// <param name="buf"></param>
        private void ReceiveMsg_Show(Byte[] buf)
        {
            if (txtReceiveMsg.InvokeRequired)
            {
                // 当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想访问它
                this.txtReceiveMsg.Invoke(ShowReceiveMsg, buf);
            }
            else
            {
                this.txtReceiveMsg.Text += Change16ToStr(buf);
            }
        }

        /// <summary>
        /// 串口数据接收事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            Thread.Sleep(100);
            int n = serialPort.BytesToRead;        //记录下数据长度
            byte[] BUF_receive = new byte[n];
            serialPort.Read(BUF_receive, 0, n);    //读取缓存数据
            ShowReceiveMsg(BUF_receive);
        }

在上面的示例代码中,SendMsg_Show函数中通过判断txtSendMsg控件的InvokeRequired属性来确定是否需要使用Invoke方法。如果需要跨线程调用,就使用Invoke方法来执行委托;否则直接更新控件内容。

也可以直接用虚方法的方式来做,不要额外定义委托对象

csharp 复制代码
        private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            Thread.Sleep(100);
            int n = serialPort.BytesToRead;        //记录下数据长度
            byte[] BUF_receive = new byte[n];
            serialPort.Read(BUF_receive, 0, n);    //读取缓存数据
            ReceiveMsg_Show(BUF_receive);
        }
       
        private void ReceiveMsg_Show(Byte[] buf)
        {
            // 判断是否需要跨线程调用
            if (txtReceiveMsg.InvokeRequired)
            {
                this.Invoke(new MethodInvoker(delegate { ReceiveMsg_Show(buf); }));
            }
            else
            {
                // 直接调用方法
                this.txtReceiveMsg.Text += Change16ToStr(buf);
            }
        }
csharp 复制代码
         this.Invoke((EventHandler)(delegate
         {
             this.txtSendMsg.Text = Change16ToStr(buf);
         }));

也可以直接在后台线程中通过这种方式直接访问控件

相关推荐
FL16238631292 小时前
[C#][winform]segment-anything分割万物部署onnx模型一键抠图演示
开发语言·c#
love530love4 小时前
OpenClaw 手机直连配置全流程
人工智能·windows·python·智能手机·c#·agent·openclaw
bcbobo21cn5 小时前
C# byte类型和byte数组的使用
开发语言·c#·字节数组·byte类型
月巴月巴白勺合鸟月半7 小时前
一次PDF文件的处理(一)
pdf·c#
大鹏说大话9 小时前
Java 锁膨胀机制深度解析:从偏向锁到重量级锁的进化之路
开发语言·c#
武藤一雄10 小时前
WPF处理耗时操作的7种方法
microsoft·c#·.net·wpf
武藤一雄11 小时前
C#常见面试题100问 (第一弹)
windows·microsoft·面试·c#·.net·.netcore
l1t13 小时前
DeepSeek总结的用 C# 构建 DuckDB 插件说明
前端·数据库·c#·插件·duckdb
iReachers14 小时前
恒盾C#混淆加密大师 1.4.5 最新2026版本发布 (附CSDN下载地址)
c#·c#混淆·c#加密·wpf加密·winform加密
历程里程碑15 小时前
43. TCP -2实现英文查中文功能
java·linux·开发语言·c++·udp·c#·排序算法