串口收发的丢包问题

squaref 2016-09-01 12:36:21
电脑接了两个设备,1个是串口连了仪表,1个是通过无线连了设备。
要求定时收发串口设备的数据和无线设备的数据,并绘制曲线。

串口的收发是通过串口类,收发都是单独线程,画图是在接收线程里,用了托管的方法刷新主界面,定时是通过DispatcherTimer实现;
无线设备负责定时收数据,定时通过timer类实现,收数据(包括画图)也是写在单独线程中工作。
程序如果单独做串口或者无线的设备功能,一切正常;但是当同时收连个设备数据的时候,串口的数据经常丢,界面也卡。
已经没招了,请大家给点建议。
...全文
3105 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
squaref 2016-09-01
  • 打赏
  • 举报
回复
说错了,串口收数据是线程实时接收的,用的队列并缓存的,不是定时。 当收满指定长度后进行判断处理。 现在问题就卡在这里了,经常不能满足处理的条件。
  • 打赏
  • 举报
回复
此外,所谓的“线程”应该在几毫秒、几十毫秒就释放掉。如果你弄了什么“死循环”的线程,那么反而并也不能保证高并发处理,而且程序只会更大、更乱(因为你多余地纠结什么“队列”)、完全不能及时响应数据接收。
  • 打赏
  • 举报
回复
发数据使用 timer 是可以理解的,收数据是数据来了就需要立刻接收,并且接收到一些数据(不等消息处理线程开始处理)就应该释放I/O线程用来接收后边的消息,怎么可能跟 timer 扯上关系呢? 定时“收”消息,这是一个纯粹外道的描述,是错误的逻辑。
squaref 2016-09-01
  • 打赏
  • 举报
回复
如果将串口的定时发送时间增加1倍,比如说从500ms增加到1000ms,那么就没有这样的情况,一切正常。
squaref 2016-09-01
  • 打赏
  • 举报
回复
相关变量定义: private static Thread _ComSend;//发送串口命令数据线程 Queue recQueue = new Queue();//接收串口数据过程中,接收数据线程与数据处理线程直接传递的队列,先进先出 ///////////////////////////////////// 页面load的相关代码: ComPort.DataReceived += new SerialDataReceivedEventHandler(ComReceive);//串口接收中断 autoSendTick.Tick += new EventHandler(autoSend);//定时发送中断,这是用于串口发送数据的定时器 ti.Elapsed += new ElapsedEventHandler(ti_Elapsed);//这是用于接收无线数据的定时器;ti_Elapsed是自己写的无线数据接收的函数; #if MULTITHREAD Thread _ComRec = new Thread(new ThreadStart(ComRec)); //查询串口接收数据线程声明 _ComRec.Start();//启动线程 #endif /////////////////////////////////////////////以下是具体函数 void Send()//发送读串口数据的命令 { #if MULTITHREAD if (Sending == true) return;//如果当前正在发送,则取消本次发送,本句注释后,可能阻塞在ComSend的lock处 _ComSend = new Thread(new ParameterizedThreadStart(ComSend)); //new发送线程 SendSet.SendSetData = sendTBox.Text;//发送数据线程传递参数的结构体--发送的数据 _ComSend.Start(SendSet);//发送线程启动 } private void ComSend(Object obj)//发送数据 独立线程方法 发送数据时UI可以响应 代码略 private void ComReceive(object sender, SerialDataReceivedEventArgs e)//接收数据 中断只标志有数据需要读取,读取操作在中断外进行 { if (WaitClose) return;//如果正在关闭串口,则直接返回 Thread.Sleep(10);//发送和接收均为文本时,接收中为加入判断是否为文字的算法,发送你(C4E3),接收可能识别为C4,E3,可用在这里加延时解决 if (recStaus)//如果已经开启接收 { byte[] recBuffer;//接收缓冲区 try { recBuffer = new byte[ComPort.BytesToRead];//接收数据缓存大小 ComPort.Read(recBuffer, 0, recBuffer.Length);//读取数据 recQueue.Enqueue(recBuffer);//读取数据入列Enqueue(全局) } } void ComRec()//接收线程,窗口初始化中就开始启动运行 { while (true)//一直查询串口接收线程中是否有新数据 { if (recQueue.Count > 0)//当串口接收线程中有新的数据时候,队列中有新进的成员recQueue.Count > 0 { //判断接收的数据是否满足长度要求; //////问题就在这儿,刚开始几秒是正常的,后面就会卡住,接收的数据越来越多,不能满足这个条件,界面也就卡死了。 } }
  • 打赏
  • 举报
回复
你的所谓的“队列”到底是什么呢?贴出你的关键代码来说明。如果只是 List<byte> 这种,这不叫队列。 队列不是针对 byte 的队列,队列是针对高级的“自定义任务对象”的数据结构。类似10 年前的一些 java 书那样的程序,是多进程的(而不是多线程的),粗粒度的任务对象需要不断跨进程传递,因此才有队列概念。后来一些垃圾 java 小文章则滥用了队列概念。 在你的多线程并发 .net 程序中,要什么任务队列?
  • 打赏
  • 举报
回复
引用 5 楼 squaref 的回复:
应该还是在收串口的数据上,总感觉与另一个timer线程干扰。
队列不但慢,多余做了许多工作,你就多了许多“干扰”(因为你多多写了许多代码)。 你有什么必要使用“队列”?贴出你的设计来。
squaref 2016-09-01
  • 打赏
  • 举报
回复
应该还是在收串口的数据上,总感觉与另一个timer线程干扰。
Poopaye 2016-09-01
  • 打赏
  • 举报
回复
请先自己明确卡在哪些语句上。

4,816

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 图表区
社区管理员
  • 图表区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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