SerialPort.DataRecive使用过程中的注意事项

.NET Framework中提供的串口操作类SerialPort已经用了很多年了,但是今天同事碰到一个问题,给我问住了。

我才发现用了这么多年的SerialPort还是有一些我所不知道的注意事项。

问题描述:同事在SerialPort的DataRecive绑定事件方法中,用了一个while循环,来处理串口接收缓冲区中的数据。但是同样的处理逻辑,放在不同的地方使用,发现不同的问题。

都是在DataRecive事件中,用while循环处理缓冲区数据,但是发现其中一个项目中,DataRecive事件会多次触发,而另一个项目中,会一直在第一次触发DataRecive事件中的while循环中转,不会触发第二次DataRecive事件。

然后搞笑的来了,我当时按照对事件最基本的运行机制的理解,解释说:事件的触发,无论前一次触发有没有完成,都不会影响第二次触发时的执行。所以一直在DataRecive中的while循环中转,肯定是有哪里影响了。

但是后来发现,我的判断错误了。

对于SerialPort中的DataRecive事件来说,前一次触发未完成时,是不会有第二次触发的。

后来反编译了一下SerialPort,证实了上述结论:

 

    public void Open()
    {
        if (IsOpen)
        {
            throw new InvalidOperationException(SR.GetString("Port_already_open"));
        }
        new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
        internalSerialStream = new SerialStream(portName, baudRate, parity, dataBits, stopBits, readTimeout, writeTimeout, handshake, dtrEnable, rtsEnable, discardNull, parityReplace);
        internalSerialStream.SetBufferSizes(readBufferSize, writeBufferSize);
        internalSerialStream.ErrorReceived += CatchErrorEvents;
        internalSerialStream.PinChanged += CatchPinChangedEvents;
        internalSerialStream.DataReceived += CatchReceivedEvents;
    }

 

    private void CatchReceivedEvents(object src, SerialDataReceivedEventArgs e)
    {
        SerialDataReceivedEventHandler dataReceived = this.DataReceived;
        SerialStream serialStream = internalSerialStream;
        if (dataReceived == null || serialStream == null)
        {
            return;
        }
        lock (serialStream)
        {
            bool flag = false;
            try
            {
                flag = serialStream.IsOpen && (SerialData.Eof == e.EventType || BytesToRead >= receivedBytesThreshold);
            }
            catch
            {
            }
            finally
            {
                if (flag)
                {
                    dataReceived(this, e);
                }
            }
        }
    }

 

从上面SerialPort的代码可以看出,对dataRecived事件的调用是加了锁的,也就是说,dataRecived事件如果没有执行完,那么后续是不会再次触发的。

 

posted on 2022-06-23 17:21  双子双星  阅读(323)  评论(0编辑  收藏  举报

导航