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);
         }));

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

相关推荐
吴可可1234 小时前
C#用OpenCVSharp提取轮廓生成CAD多段线
c#
玖玥拾7 小时前
Unity 3D 笔记(十四)Unity/C# Socket 网络笔记3
服务器·网络·unity·c#
玖玥拾9 小时前
Unity 3D 笔记(十七)Unity/C# Socket 网络笔记6
服务器·网络·unity·c#
geovindu10 小时前
CSharp: Iterative Algorithms
开发语言·后端·算法·c#·.net·迭代算法
影寂ldy10 小时前
C# HttpClient 分片下载、断点续传、暂停取消(完整项目知识点)
开发语言·c#
code bean11 小时前
【C#】 主构造函数(Primary Constructors)的来龙去脉
开发语言·c#
Suxing912 小时前
C语言基础分享:“群租房”和“点名册”——联合体与枚举
c语言·算法·c#
czhc114007566312 小时前
725: [property: XmlIgnore]
c#
kingwebo'sZone12 小时前
C#事件声明办法
java·前端·c#
ye小杰榨 问鼎中原ZP13 小时前
关于对 C# 中 ImplicitUsings,GlobalUsings 的讨论
服务器·开发语言·c#