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

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

相关推荐
张人玉3 小时前
C# TCP 客户端开发笔记(TcpClient)
笔记·tcp/ip·c#
张人玉6 小时前
C# 通讯关键类的API
开发语言·c#
William_cl14 小时前
C# MVC 修复DataTable时间排序以及中英文系统的时间筛选问题
开发语言·c#·mvc
c#上位机14 小时前
wpf之RelativeSource用法总结
c#·wpf
Dm_dotnet15 小时前
WPF应用最小化到系统托盘
c#
*长铗归来*17 小时前
ASP.NET Core Web API 中控制器操作的返回类型及Swagger
后端·c#·asp.net·.netcore
R-G-B19 小时前
【06】C#入门到精通——C# 多个 .cs文件项目 同一项目下添加多个 .cs文件
开发语言·c#·c# 多个 .cs文件项目
懒人Ethan1 天前
解决一个C# 在Framework 4.5反序列化的问题
java·前端·c#
mysolisoft2 天前
Avalonia+ReactiveUI实现记录自动更新
c#·avalonia·reactiveui·sourcegenerator
心疼你的一切2 天前
使用Unity引擎开发Rokid主机应用的模型交互操作
游戏·ui·unity·c#·游戏引擎·交互