(七)C# serialPortObj.ReadTimeout的应用:解决“System.TimeoutException”操作已超时的问题

一、简介

      结合了我之前的一篇博客,在C#中,下面的几个接收函数,读取接收缓存器时,会发生超时异常。比如:

     private void Recieve(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                #region 以下5种方法,实用性不广,不建议采用。如果要用,可以参考官网
                //string s2 = SerialPortObj.ReadLine();//读取接收缓存器中的新行的值。超时会发生异常。
                //string s3 = SerialPortObj.ReadTo("XXX");//读取接收缓存器中的特定字符串的值。超时会发生异常。
                //string s1 = SerialPortObj.ReadExisting();//读取接收缓存器中的所有字节,并将其转换为字符串。超时不会发生异常
                //int i1 = SerialPortObj.ReadByte();//读取一个字节并返回整数,超时会发生异常。
                //int i2 = SerialPortObj.ReadChar();//读取一个字符并返回整数,超时会发生异常。
                #endregion

                #region 建议采用第6种方法
                开辟接收缓冲区
                byte[] bytReceiveData = new byte[SerialPortObj.BytesToRead];
                SerialPortObj.Read(bytReceiveData, 0, bytReceiveData.Length); //从串口读取数据
                //一旦接收彩屏的曝光指令,PC马上返回当前的曝光值
                SendExposeValues(bytReceiveData);

                //调用委托,将字符信息显示在TextBox控件上。
                _recievedData = System.Text.Encoding.Default.GetString(bytReceiveData);
                Dispatcher.Invoke(DispatcherPriority.Send, new UpdateUiTextDelegate(WriteDate), _recievedData);
                #endregion
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }        
        }

         前5个方法,局限性比较大,不如第六哥方法使用,建议采用第六个方法。

二、超时异常函数及其应用    

        关于前三个方法,是超时方法。

       我们先来看看超时异常,看看每个接收函数超时的效果。以下操作,用串口助手发数据进行测试:

2.1、SerialPortObj.ReadExisting();//读取接收缓存器中的所有字节,并将其转换为字符串。超时不会发生异常。

        其他省略,见官网的超时问题:

https://docs.microsoft.com/zh-cn/dotnet/api/system.io.ports.serialport.readtimeout?view=netframework-4.8

https://blog.csdn.net/xpj8888/article/details/84628762(我的上一篇博客)

三、如何在特定时间内,非阻塞提取接收缓存器里面的全部有效字节?

      注意啊,本章节的标题,我用到了下面的4个关键词:

  • 特定时间——间隔特性时间(经验值500ms)扫描一次缓存器,直到收完,保证完整信息。

  • 接收缓存器——缓存器一旦有数据,会触发事件接收serialPortObj.DataReceive+= receive()

  • 有效字节——确保数据包的完整,避免拆包。

  • 非阻塞——线程接收,防止阻塞

         要接收字节,必须用下面的 SerialPortObj.Read这个函数:

byte[] bytReceiveData = new byte[SerialPortObj.BytesToRead];
SerialPortObj.Read(bytReceiveData, 0, bytReceiveData.Length); //从串口读取数据

       但是,怎么理解  提取接收缓存器里面的全部有效字节?那就是,假如我发送了10字节有效字节,接收缓存器可能第一次接收3个字节,第二次可能接收7个字节。那么3 + 7 = 10,才是我的完整信息。那该怎么办呢?我应该一直读取接收缓存器,分别把3和7都放在一个接收队列中,直到接收缓存器没有收到任何信息,这时,接收队列中的10个字节才是有效的、才是完整的。

https://bbs.csdn.net/topics/320016645

https://bbs.csdn.net/topics/390730988?locationNum=6&fps=1

 

 

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我爱AI

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值