多线程程序设计.....
前几天我的同事告诉我一个奇怪的事情那就是他用我的软件通过无线电台与终端进行通信的的时候(这里的终端是指以单片机为核心的硬件设备),发现通信的可靠率很低,只有大约在30% ~60%之间,而且很不稳定,可是以前很长时间从来没有出现过这种问题,以前可以这么说就是100%的可靠率的呀!
后来把与无线电台进行通信的RS232串口的第2线与第3线进行对接,然后用两个串口进行调试,首先我用我有软件进行数据的发送与接收,然后用串口调试助手进行从另一个串口进行接收,发现果然是没有发送完全,打个比方说.另一个软件通过TCP连接到这个软件后,在相当短的时间请求发送独立三次数据,但是我通过串口助手接收的只有一次数据,有时会是二次数据,这时我心里就开始纳闷了,因为这种情况是不是总是一样的!
没有办法,只是打开VC在源代码进行调试,我发现一个很奇怪的现象,那就是通常第一次一定能发送成功,但是由于终端没有回数据,所有我要返回一个超时的命令,但是第二次数据通常是发送不出去的,有时第三次数据能够发送成功!用无线电台进行数据发送有一个特别的地方就是有关RTS的设置,关于这一点我以前写过的一篇文章中,可参见这一篇.http://www.vccode.com/file_show.php?id=2817.
想到因为是不是一定会出现某种现象,我突然想到可能是多线程的地方的出了问题!最终被解决了问题,我想原因可能是这样的.
首先为什么会第一次发送成功,因为这个终端是单工的,所以当当前通道正在忙的情况,对于后面的数据发送请求只能是等待,而且每发送完一次数据,如果终端在一定时间不回数据,要给出一个超时,我用的是设计好的一组线程池,当收到数据后首先进行解释后,放入到一个队列,当然一定要保证是线程安全的,当数据正在发送的时候,如果又有数据进入以后,让其在外等待,以前我的做法是如果不可以发送就直接在线程中退出来,会有另外一个线程对这个队列进行定时的检查,如果有超时的任务,则提示是哪个任务超时了,这时这个通道是可以用的,注意在发送过程中这个通道是不可以用的,我的错误就是没有一种机制通知当有任务超时的时候去通知这个通讯线程池现在某某通道可以被利用了,你们如果谁有数据没有发送的赶快来进行发送了,我想可能就是这个地方错误了!知道为什么问题就比较好弄了,解决方法是这样的,先告诉你解决后数据通讯可靠率是100%,性能very good!!!
当发送第一个任务后,如果需要等待终端的应答的话,这时启动一个定时器,同时指定一个回调函数,这个定时器的间隔要有一个的算法,因为线程的上下文进行切换,通常不能保证非常的精确,这个对于我们来说就有问题了,因为串口接收对时间要求很严格,所以我们把定时器的间隔相对小一点,但又不能太小(小于100ms)就不能保证了,除非用高精度的定时器(好像没有那个必要).在这个回调函数中对任务检查超时,如果超时的话,这时我会检查任务队列是否有人还有数据需要发送,哈哈,这时有的话也不能直接发送,因为在这个发送函数中有Sleep(...).所以不能直接有主线程中发送了,不然别人会以为你那是死机了,你会死的比较难看的,这时会用一个事件通知一个正在等待这个事件的线程,线程等到以后做些什么,俺就不啰嗦了....
这个问题被解决了以后,又发现另外一个问题,我在调试串口的时候,我的那个ThinkPad 没有串口,所有只好用USBtoRS232,用了快半年都没有出过问题,后来在另外一台有串口的机器发现数据接收不完整,唉呀呀, 只好想一想,想呀想,原来是因为......
USBtoRS232可能在两个数据的间隔的发送与接收比那个直接的串口要快那么N毫秒吧,这个问题解决了,调整接收间隔,降低了接收的速率了,这时收发很稳定了.....
通过这两个事情,让我们程序员要以软件的质量为目标,做事要相当的严谨,不能有一丝马虎,必须不能有一丝的侥幸心理,要想提高软件质量,要不断的学习,学习.......