Victor 1.5.0.6 for BCB6串口 VCL/FMX 控件在大数据接收报ERROR_I0_PENDING及ERROR_IO_INCOMPLETE导致卡住问题

现在各种QT python ide用起来很方便,但生成的程序太大不方便,个人平时还是喜欢用c++builder写一些小测试程序,程序可以做到很小巧。

TYbCommDevice 是c++ builder的很方便的一个串口收发控件,目前最新版是1.5.0.6,在官网看到是2017年后就没有更新。

最新利用TYbCommDevice写了一个测试程序接收并解释由MCU发上来的持续数据,波特率是115200bps,使用USB转口模块转发数据。

测试过程发现在接收大量,及持续数据时,经常会出现读线程阻塞,导致系统卡住的问题。

1. 分析初步原因是ReadFile及GetOverlappedResult函数读取失败,导致变量BytesRemain没有自减至0而导致while(BytesRemain>0)无法退出

2. 估计的实质原因是ReadFile及是GetOverlappedResult函数调用过快引起IO申请过于频繁引起的系统异常,报ERROR_IO_INCOMPLETE错误

注:ERROR_I0_PENDING表示读取IO操作是异步的并且尚未完成, ERROR_IO_INCOMPLETE表示I/O操作仍在进行中尚未完成,

其实ReadFile函数在非串口数据读取的其它场合,调用过快引起IO申请太频繁也会引发ERROR_I0_PENDING/ERROR_IO_INCOMPLETE错误导致意想不到的异常,尤其在CPU运行速度越来越快的情况下,所以需要合理使用此函数,比如使用定时器(降实时性换稳定性),或者当查询到的数据量大于一定值再调用ReadFile(一个字节调用一次就有点频繁了)

解决方案:

如出现上述两种情况,尝试使用CancelIo函数取消当前的IO申请并休眠1ms,经长时间测试仍稳定接收,未测出异常(原测试不超过10分钟就挂掉)

如有需要可以下载我编译好控件及库(有源码):

VictorComm1506-VCL-CB6-FIX(20230917)串口控件库及源码(修复串口持续接收高波特率数据异常问题)资源-CSDN文库

           if(dwEvtMask & EV_RXCHAR)
            {
              ClearCommError(Comm->Handle, &dwErrorFlag, &ComStat);
              BytesRemain = ComStat.cbInQue;

              while(BytesRemain>0)
               {
                 BytesToRead = BytesRemain<RecvBufSize?BytesRemain:RecvBufSize;

                 if(ReadFile(Comm->Handle, RecvBuf, BytesToRead, &dwBytes, &Comm->_ReadOS))
                  {
                    Comm->_InQueue->In(RecvBuf, dwBytes);
                    BytesRemain-=dwBytes;
                  }
                 else
                  {
                    DWORD dwError = GetLastError();
                    if(dwError==ERROR_IO_PENDING)
                     {
                       if(GetOverlappedResult(Comm->Handle, &Comm->_ReadOS, &dwBytes, false))
                        {
                          Comm->_InQueue->In(RecvBuf, dwBytes);
                          BytesRemain-=dwBytes;
                          retry = 0;
                        }
                        else
                        {
                          dwError = GetLastError();
                          /* 测试过程中,在高波特率,接收大量,及持续数据时,经常会出现读线程阻塞,系统卡住的问题
                             1. 分析初步原因是ReadFile及GetOverlappedResult函数读取失败,导致变量BytesRemain没有自减至0而导致while(BytesRemain>0)无法退出
                             2. 估计的实质原因是ReadFile及是GetOverlappedResult函数调用过快引起IO申请过于频繁引起的系统异常,报ERROR_IO_INCOMPLETE错误
                             ERROR_I0_PENDING表示读取IO操作是异步的并且尚未完成, ERROR_IO_INCOMPLETE表示I/O操作仍在进行中尚未完成
                             修改方案:
                             如出现上述两种情况,尝试使用CancelIo函数取消当前的IO申请并休眠1ms,经长时间测试仍稳定接收,未测出异常(原测试不超过10分钟就挂掉)
                          */
                          if((dwError==ERROR_IO_INCOMPLETE)||(dwError==ERROR_IO_PENDING))
                          {
                            CancelIo(Comm->Handle);
                            Sleep(1);
                          }
                          // retry 500ms
                          if(retry++>500)
                          {
                              CancelIo(Comm->Handle);
                              BytesRemain = 0;  // error, give up retry!
                          }
                        }
                     }
                  }
               }
            }

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值