自从用上了C#,那真的叫一个爽,再也不用写函数声明,再也不用去手动释放内存,一个ToString函数,基本所有的类型转换都完成… …
但是爽是有代价的,比如用着用着毫无征兆的退出了,比如,程序里面一堆堆的try catch仍旧抓不到那个错误在哪里… …
如果以上的问题都可以容忍,依旧会有问题你没有办法容忍,比如今天要说的SerialPotr类阻塞问题。
该程序是COBAS8000电化学发光分析仪的接口,一开始就是用c#写的,使用了c#自带的SerailPort类。
先说说程序逻辑:
1、接口程序收到COBAS8000发送的条码请求。
2、接口程序到LIS数据库中找到要做的相应的项目。
3、接口程序发送ENQ.
4、仪器回复ACK后,接口程序将要做的项目发送给仪器。
发送部分的核心代码如下:
代码如下 | 复制代码 |
public void SendOrder(OrderRecord order) string strSend = ""; strSend += Encoding.ASCII.GetString(order.GetBytes()); byte[] btSend=this.GetFrameBytes(Encoding.ASCII.GetBytes(strSend)); Log log = new Log(); this.sendBytes = btSend; this.State = ComState.Sending; this.IsSended = false; log.Write("马上发送ENQ!"); dtENQSend = DateTime.Now; } |
现在我们遇到的问题是:当接口程序收到条码请求,并在LIS中找到了项目,然后准备发送ENQ给设备的时候,卡死了!!!!!!
从日志上看,程序就停留在(”马上发送ENQ!”)不动了!
调用的函数是:
代码如下 | 复制代码 |
serialPort.Write(bytes, 0, bytes.Length); |
到这里程序就死了。
由于COBAS8000的超时时间是18秒,等到18秒后,仪器就将该条码的标本当做没有项目处理了,之后,它将继续发送下一个条码的请求!然后程序就又活了!!!!
于是乎,我写的那个接口每天就出现这样一种情况:
当大批量的标本上机之后,中间总会有一两个没有项目,将这两个标本挑出来,再上一遍,它又好了!!!
吵吵尝试和排除了以下几种情况:
1、由于UI和界面造成的程序假死,使得serialport没有将信息发送成功,于是我取消了所有的UI,经大规模标本测试,依旧会有一两个扫不上!
2、由于线程造成的锁死,于是乎我重新将读取放到一个独立的线程,使得串口的读写进行了分离,结果呢,还是会出问题。
最大的问题是平常标本不多的时候,一点问题都没有,大规模标本上上去后,就一两个出问题,serialPort的write方法,肯定在某个地方是有问题的,兴许是线程阻塞吧,但是由于看不到源代码,着实没有办法去跟踪解决。而且偶尔出现问题,这个问题本身就很难解决。
最后,祭出我的杀手锏,用串口的API来写吧,考虑到我原来在C++中用的多线程串口类很成熟,于是乎花了四天时间,用c++重新写了接口。调试了两个多月的问题,其实还不如四天重写解决问题快!
最后总结一下,如果要求高的程序,c/c++依旧是主流,c#么?开发之前,一定要考虑好,一定要做好出问题的打算