C# 如果串口的DataReceived事件处理接收到的数据还没处理完,缓冲区又有数据了,此时会再次触发DataReceived事件么?

C#菜鸟June 2018-08-25 12:49:42
(1)如果DataReceived事件处理接收到的数据还没处理完,缓冲区又有数据了,那么此时是再次触发DataReceived事件,还是等上次的DataReceived事件处理完成,再触发?
(2) 如果每隔50ms发送一个指令到串口,使用DataReceived事件接收返回的值,很容易出现第一条指令的回文还没有接收完全,到50ms第二条指令又发出去了,那第一条指令的回文没有接收全,岂不是要丢掉?

使用的是RS485
...全文
1574 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
Wxy巫巫 2019-05-07
  • 打赏
  • 举报
回复
引用 3 楼 以专业开发人员为伍 的回复:
在设计(串行)消息信令时,如果考虑到异步并发地发送和解析处理的需求,就会对消息进行编号。同时流式信息处理自然就是要处理分包和粘包的过程,你收到一个消息的结束标志标志之后才会从之前接收的所有内容之中去分割收到的一个或者多个消息(并且留下剩下的未收到信令结束标志的内容),然后异步并发地解析处理收到的各个消息。要设计好程序流程,首先要学会换一种思路、假设自己是个根本不懂计算机软件的人,要学会找到隐喻。切不可因为纠结、抠字眼儿一点点计算机术语而把脑袋烧坏了。
你好,请问怎么处理接收到的数据粘包的问题,就是我现在串口缓存区当串口读取时会一下接收到好几个节点发送过来的数据包,我该怎么分割出单个的数据包,如果分割除了第一条数据包,进行处理后,那缓存区后面的数据包怎么办?怎么才能实现将缓存区的多条数据包分割后,循环处理单个的数据包呢?
LaiLai_Fido 2018-12-20
  • 打赏
  • 举报
回复
引用 楼主 june905206961 的回复:
(1)如果DataReceived事件处理接收到的数据还没处理完,缓冲区又有数据了,那么此时是再次触发DataReceived事件,还是等上次的DataReceived事件处理完成,再触发? (2) 如果每隔50ms发送一个指令到串口,使用DataReceived事件接收返回的值,很容易出现第一条指令的回文还没有接收完全,到50ms第二条指令又发出去了,那第一条指令的回文没有接收全,岂不是要丢掉? 使用的是RS485
LZ,不知道你有没有解决这个问题?我现在碰到了与你类似的情况
C#菜鸟June 2018-08-25
  • 打赏
  • 举报
回复
这两个问题一直困扰着我,请各位大神指教一下!,刚接触串口
C#菜鸟June 2018-08-25
  • 打赏
  • 举报
回复
引用 4 楼 sp1234 的回复:
过程执行完毕才会触发窗口下一个 DataReceived 事件 --> 过程执行完毕才会触发串口下一个 DataReceived 事件


不管是底层的 I/O 线程是同步还是异步处理,它基本上都能保证是顺序抛出事件。例如异步接收数据,那么在一个事件过程执行完毕之后才会去开始注册下一个委托回调。不管是同步还是异步处理 I/O,它们都不会并发抛出事件,而是顺序抛出事件。

谢谢,通过您的回答,第一个问题已经明白了!
C#菜鸟June 2018-08-25
  • 打赏
  • 举报
回复
引用 5 楼 Snowwolf_119 的回复:
RS485通讯,发送是一个缓冲区,接收是一个缓冲区,所以根本不存在你说的第二条发送,丢弃第一条回文的情况。
发送缓冲区会在发送每条数据前或后清空,接收缓冲区只是提取数据,不会清空。
RS485通讯会存在一定的时延,所以要做好发送和接收的同步。

我用的是485半双工的,同一时间只能收或者发,这样就完全会出现我第二条问题啊
雪狼孤竹 2018-08-25
  • 打赏
  • 举报
回复
RS485通讯,发送是一个缓冲区,接收是一个缓冲区,所以根本不存在你说的第二条发送,丢弃第一条回文的情况。
发送缓冲区会在发送每条数据前或后清空,接收缓冲区只是提取数据,不会清空。
RS485通讯会存在一定的时延,所以要做好发送和接收的同步。
  • 打赏
  • 举报
回复
过程执行完毕才会触发窗口下一个 DataReceived 事件 --> 过程执行完毕才会触发串口下一个 DataReceived 事件


不管是底层的 I/O 线程是同步还是异步处理,它基本上都能保证是顺序抛出事件。例如异步接收数据,那么在一个事件过程执行完毕之后才会去开始注册下一个委托回调。不管是同步还是异步处理 I/O,它们都不会并发抛出事件,而是顺序抛出事件。
  • 打赏
  • 举报
回复
在设计(串行)消息信令时,如果考虑到异步并发地发送和解析处理的需求,就会对消息进行编号。同时流式信息处理自然就是要处理分包和粘包的过程,你收到一个消息的结束标志标志之后才会从之前接收的所有内容之中去分割收到的一个或者多个消息(并且留下剩下的未收到信令结束标志的内容),然后异步并发地解析处理收到的各个消息。要设计好程序流程,首先要学会换一种思路、假设自己是个根本不懂计算机软件的人,要学会找到隐喻。切不可因为纠结、抠字眼儿一点点计算机术语而把脑袋烧坏了。
  • 打赏
  • 举报
回复 1
不会。DataReceived 事件处理过程执行完毕才会触发窗口下一个 DataReceived 事件。所以在你的过程中,读取数据到你的处理缓冲之后,应该尽量异步地解析和处理数据,这样就可以立刻释放 I/O 线程,而仅仅用你的 Worker 线程来解析和处理实际数据。

当然这要根据编程者的能力来决定结果,有时候如果你只是临时做个最初级的“练习”(例如 msdn 上关于通讯的代码几乎都是初级的、为了演示而写代码的、许多设计理念都是最低级的、仅仅为了说明语句语法的,所以 msdn 上的通讯代码是最垃圾的一种代码)那么你可以用阻塞和同步的传统思路。假设你需要考虑异步并发设计,那么你必定要把设计思路往高级一些去考虑。

编程设计的最基础的是要学会找到隐喻。比如说你收到了最低级的一堆电报搞之后,你的下属有5个人分别负责译电,那么他们异步并发地各自工作,将结果交给你之后你又是怎样能够准确地区分哪一份电文的来源呢?

同样的道理。编程设计的最基础的技能是会找到隐喻。有的人连异步并发的消息解析和处理的机制都设计不出来,就是因为他连生活常识都想不明白,而不是什么编程语句不了解的问题。
  • 打赏
  • 举报
回复
lz 的第二个问题是基于第一个问题来提问的。假设第一个问题是错误的答案,那么第二个问题自然就会成立!第一个问题如果搞明白了,就不存在第二个问题,只是要说明如何优化第二个问题的编程设计而已。
  • 打赏
  • 举报
回复
引用 5 楼 Snowwolf_119 的回复:
RS485通讯,发送是一个缓冲区,接收是一个缓冲区,所以根本不存在你说的第二条发送,丢弃第一条回文的情况。
发送缓冲区会在发送每条数据前或后清空,接收缓冲区只是提取数据,不会清空。
RS485通讯会存在一定的时延,所以要做好发送和接收的同步。


lz 问的是两个 I/O 线程会不会并发执行 DataReceived 方法的问题。
  • 打赏
  • 举报
回复
如果一个串口同时被从两个线程都触发 DataReceived 方法,那此时说什么底层术语(包括.net 应用本身不需要关心的东西)都没法解释该如何编程设计的问题。
串行通信主要用了C# 中的SerialPort类 开发语言:C# 程序运行环境:.NetFrameWork 2.0以上版本 开发工具:Visual Studio 2008 C# System.IO.Ports命名空间包含了控制串口重要的SerialPort类,该类提供了同步 I/O 和事件驱动的 I/O、对管脚和中断状态的访问以 及对串行驱动程序属性的访问,所以在程序代码起始位置需加入Using System.IO.Ports。 串口的通讯参数 a.通讯端口号 [PortName]属性获取或设置通信端口,包括但不限于所有可用的 COM 端口,请注意该属性返回类型为String。通常情况下,PortName正 常返回的值为CO1、COM2……,SerialPort类最大支持的端口数突破了CommPort控件中CommPort属性不能超过16的限止,大大方便了用户 串口设备的配置。 b. 通讯格式 SerialPort类对分别用[BaudRate]、[Parity]、[DataBits]、[StopBits]属性设置通讯格式中的波特率、数据位、停止位和校验位,其 中[Parity]和[StopBits]分别是枚举类型Parity、StopBits,Parity类型中枚举了Odd(奇)、Even(偶)、Mark、None、Space,Parity枚 举了None、One、OnePointFive、Two。 SerialPort类提供了七个重载的构造函数,既可以对已经实例化的SerialPort对象设置上述相关属性的值,也可以使用指定的端口名称 、波特率和奇偶校验位数据位和停止位直接初始化 SerialPort 类的新实例。 3.串口的打开和关闭 SerialPort类是调用类的Open()和Close()方法。 4. 数据的发送和读取 Serial类调用重载的Write和WriteLine方法发送数据,其中WriteLine可发送字符串并在字符串末尾加入换行符,读取串口缓冲区的方法 有许多,其中除了ReadExisting和ReadTo,其余的方法都是同步调用,线程被阻塞直到缓冲区有相应的数据或大于ReadTimeOut属性设定 的时间值后,引发ReadExisting异常。 5.DataReceived事件事件类似于MSComm控件中的OnComm事件DataReceived事件接收到了[ReceivedBytesThreshold]设置的字符个数或接收到了文件结 束字符并将其放入了输入缓冲区时被触发。其中[ReceivedBytesThreshold]相当于MSComm控件的[Rthreshold]属性,该事件的用法与 MsComm控件的OnComm事件在CommEvent为comEvSend和comEvEof时是一致的

110,537

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧