〖请教〗在photon程序中用串口收数据使用线程好还是定时器好?

一直都是半吊子的水平,好多问题似是而非。因为在photon下使用控件觉得挺顺手,所以在串口通信程序中也使用了定时器,每隔一定时间去读一下串口的数据,如果是正确的帧就分析找出有用数据,如果不是到下次再去读串口。另一种方案则是在photon中开启一个线程,始终在读串口的内容,同样也分析是不是正确的帧,如果是则提取数据,显示在相应控件上,否则在线程中继续读。
这两种方法哪种好
时间太紧张了,我也没时间再去调试比较,唐先生和其他专家能否告诉一下,给个提示。我只是试了一下一个简单的读取消息队列的程序,发现使用死循环读取消息队列的线程一旦运行起来,CPU完全占用为100%,而内存占用基本没什么变化。用定时器去读消息队列的话,CPU基本上是百分之几的样子,内存占用也没什么变化,而且定时器定为50ms或者10ms也没太大区别。
先谢过了!

建议用定时器,如果是用线程存在线程间的调度问题,你让它始终读的方法是错误的,这样会使其它的线程根本没有机会运行。

如果是用线程存在线程间的调度问题,你让它始终读的方法是错误的

谢谢指教!以上这句话的意思是说如果使用线程的话,自己要调度好线程,不要让它始终处于读状态,而是在某些条件下才去读吗?

比如还有另外一个线程,读串口的线程在读过后应该马上将优先权交给别的线程,当别的线程做完它的工作后再将其交回。

用定时器,比方说每50ms读一次串口,如果数据有时候可以3-4秒才来一帧的话,你就浪费了不少CPU时间(多余的读操作)。但是,因为Photon的单线程性,这样的程序相对简单一点。收到数据的处理和显示可以一步到位。

用另开一个线程的方法,要记得open()的时候不要O_NONBLOCK,这样,如果没有数据来的话,read()会被BLOCK住;一旦有数据到,read()返回,就可以继续处理,相对来说,实时性比较好。(数据到达后不用象定时器方法那样等50ms再被处理)。不过,缺点是数据处理后的显示可能费力一点。参考一下PtEnter()/PtLeave()。

顺便提一下,在实时系统的设计中,一般来讲,应该尽量采用“事件驱动”,而避免“论询”这样的程序结构。比方说,可以用中断,就不必用定时器然后论询。在通常情况下,不同的进程(线程)被阻挡在别的进程(线程)上,整个系统就好象是静止的,不占用CPU。当外界有什么“事件”发生了,比方说数据到达了,那么一些进程会被叫醒,从而叫醒别的进程,进行处理,结束后,又回到“等事件”状态。

这样的做法,大多数情况下,可以提高响应速度。同时节约了CPU消耗。当然,以上只是一般论,具体情况也有用“论询”更合理,更快速的特殊情形。

非常感谢唐先生! 在另一个贴子里,您也回答了我关于串口使用O_BLOCK的问题,因为对事件驱动的理解和实现水平都太低,现在我就先用轮询的这种方法,这样如果串口用O_BLOCK选项的话,我担心会阻塞在定时器处理程序中.不过确实又出现了唐先生所讲的"写"就不能保证了.可不可以再指点一下如何保证"写"的正确性呢,在这种轮询方式下?

O_NONBLOCK时,每一次写都要检查返回值。如果是-1,则写出错;如果等于要写的字节数(所有字节都写成功),则写成功。比较头疼的是返回值小于要写的字节数,代表只有一部份数据被写出。这时要进行特殊处理。或者是用select()等设备有空后再写,但这样会阻塞进程;还可以记住这次写有多少字节没有写出去,下一次论询/时钟时再尝试写。再一个比较QNX的办法,是用ionotify(),要求设备驱动有空时通知进程,到那时再写。

如果对将收到的帧有一定预测的话, 比如知道长度/起始字符/帧间隔/超时等, 是不是用readcond()更简单些?