问题描述
由于某种原因,串口发送被写在了一个循环里面,表示需要多次发送,然而希望是发-收-发-收这样的步调同步工作。根据跟踪,发现目前的程序必须在所有循环执行完毕,也就是所有发送动作完成后,才会去执行串口的DATARECIEVE事件,去读缓冲。如何实现这样的同步呢?发送的代码是这样的:foreach(intiFNinSelectedFN){//**AFN,FN都有了,其他在界面上填入,开始组建通信帧textFN.Text=iFN.ToString();List<byte>frame=newList<byte>(512);MakeFrame(refframe,iFN);//**然后发送这个帧stringsframe="";foreach(bytebinframe){sframe+=b.ToString("X2");sframe+="";}sframe+="rn";SendFrame(frame);this.BeginInvoke((EventHandler)(delegate{richTextBox1.AppendText(sframe);}));Thread.Sleep(3000);}根据日志文件,发送动作确实是每3秒发送一下。而函数Sendframe(frame)只是简单的调用了串口的write方法。问题是串口的DATARECIEVED是在这个循环执行完毕后,程序返回,才开始处理的。想了很久,不知道该怎么实现?用全局变量来同步?也不行,因为调试发现是发送的循环执行完才触发了读串口缓冲的动作
解决方案
解决方案二:
另外,还一个现象就是,发送时虽然使用了BeginInvoke,然而界面更新也并没有同步更新,也是在循环执行完后,界面才刷新,并不是每1个循环,界面都实时更新
解决方案三:
我也不是很懂,因为用invoke去测试UI的同步更新,并没有效果。但我可以建议你用一个TIMER,再用一个发送帧的LIST,然后用一个全局的静态BOOL参数去控制是否允许发送,TIMER定时检查发送帧的LIST,一旦发现有,且允许发送标识为真,则发送。这样串口的接收数据事件一旦触发,则首先置允许发送为FALSE,然后处理,处理完成再置允许发送标识为TRUE,这样就可以绕过你的问题。
解决方案四:
试试:每次发送根据业务需要,控制发送数量或长度
解决方案五:
试试新建一个Thread去执行这个循环
解决方案六:
将发送的过程写成一个void方法,用一个线程sendthread专门执行它,将datareceived事件添加到void方法中,用一个线程锁协调收发。具体的你看一下线程锁的简单用法就知道了。
解决方案七:
一般来说,通信最好放在Thread里执行,包括串口的通信,然后与界面的交互(一般为显示数据什么的),通过事件委托出来给主线程显示。从你给的代码来看,仅仅是执行了发送的操作,中间还让主线程沉睡了3秒(这是你界面不实时更新的原因),一般数据接收由事件触发,需重新处理的,你展示出来的代码看不出什么
解决方案八:
按照你的发-收-发-收的思想。你可以开一个线程,一直去接收串口来的字符串。另一个线程根据你接收到的字符串数据,然后用正则表达式判断接收到的是什么字符串,根据判断结果去执行想做的事情。