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

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

相关推荐
YuanlongWang4 小时前
c# 泛型的详细介绍
c#
嵌入式学习和实践6 小时前
C# WinForms 多窗口交互通信的示例-主窗口子窗口交互通信
c#·交互·主窗口-子窗口通信
专注VB编程开发20年6 小时前
C#,VB.NET数组去重复,提取键名和重复键和非重复键
c#·.net·linq·取唯一键·去重复·重复数量
YuanlongWang6 小时前
Entity Framework Core和SqlSugar的区别,详细介绍
c#
unicrom_深圳市由你创科技9 小时前
工业上位机,用Python+Qt还是C#+WPF?
python·qt·c#
偶尔的鼠标人20 小时前
Avalonia DataGrid 控件的LostFocus事件会多次触发
开发语言·c#
ytttr87320 小时前
C# 仿QQ聊天功能实现 (SQL Server数据库)
数据库·oracle·c#
future_studio1 天前
聊聊 Unity(小白专享、C# 小程序 之 图片播放器)
unity·小程序·c#
c#上位机1 天前
wpf中Grid的MouseDown 事件无法触发的原因
c#·wpf
CodeCraft Studio1 天前
国产化PDF处理控件Spire.PDF教程:如何在 C# 中从 HTML 和 PDF 模板生成 PDF
pdf·c#·html·.net·spire.pdf·pdf文档开发·html创建模板pdf