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

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

相关推荐
csdn_aspnet1 天前
C# 在逗号分割的字符串中判断是否包含指定字符
c#·正则·linq·string·regex·contains
宝桥南山1 天前
Blazor Web Assembly - 体验一下Authentication State从Server共享给Client
microsoft·微软·c#·asp.net·.net·.netcore
淡海水1 天前
02-06-历史-托管GC机制-垃圾回收如何影响数据结构选择
c#·编译·gc·机器码
longxiaozhang62 天前
C# static:静态成员,小白也能看懂
开发语言·c#
longxiaozhang62 天前
C#继承:让代码少写一点,偷懒的好方法
开发语言·c#
rockey6272 天前
C#脚本引擎之AScript与DynamicExpresso对比
c#·.net·script·动态脚本
Vae_Mars2 天前
C#中的delegate委托
开发语言·c#
公子小六2 天前
基于.NET的Windows窗体编程之WinForms音频控件
windows·microsoft·c#·.net·音视频·winforms
绿浪19842 天前
c# 结构体 能不能直接封送检测
开发语言·c#
新手unity自用笔记2 天前
unity基于Socket的网络学习
网络·网络协议·学习·unity·c#·游戏引擎