解决C# SerialPort类串口写入的阻塞问题

作者:袖梨 2022-06-25

自从用上了C#,那真的叫一个爽,再也不用写函数声明,再也不用去手动释放内存,一个ToString函数,基本所有的类型转换都完成… …

但是爽是有代价的,比如用着用着毫无征兆的退出了,比如,程序里面一堆堆的try catch仍旧抓不到那个错误在哪里… …

如果以上的问题都可以容忍,依旧会有问题你没有办法容忍,比如今天要说的SerialPotr类阻塞问题。

该程序是COBAS8000电化学发光分析仪的接口,一开始就是用c#写的,使用了c#自带的SerailPort类。


先说说程序逻辑:

1、接口程序收到COBAS8000发送的条码请求。

2、接口程序到LIS数据库中找到要做的相应的项目。

3、接口程序发送ENQ.

4、仪器回复ACK后,接口程序将要做的项目发送给仪器。

发送部分的核心代码如下:

 代码如下 复制代码

public void SendOrder(OrderRecord order)
{

    string strSend = "";
    HeaderRecord head = new HeaderRecord();
    strSend+=head.GetString();
    PatientRecord patient = new PatientRecord();
    strSend+=patient.GetString();

    strSend += Encoding.ASCII.GetString(order.GetBytes());
    TerminationRecord termination=new TerminationRecord();
    strSend += termination.GetString();

    byte[] btSend=this.GetFrameBytes(Encoding.ASCII.GetBytes(strSend));

    Log log = new Log();
    log.Write("已准备好发送数据!");   

    this.sendBytes = btSend;

    this.State = ComState.Sending;

    this.IsSended = false;

    log.Write("马上发送ENQ!");
    this.SendENQ();

    dtENQSend = DateTime.Now;
    this.IsSendingENQ = true;

}

现在我们遇到的问题是:当接口程序收到条码请求,并在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#么?开发之前,一定要考虑好,一定要做好出问题的打算

相关文章

精彩推荐