c# - WaitFor() - 如何等待特定缓冲区到达 Steam/SerialPort?

标签 c# stream serial-port tcp

请求的行为:我想听听建议的通用解决方案,以暂停调用线程,直到在流/串行端口上接收到特定缓冲区。目前,我不关心超时等问题,但我需要一些健壮的东西。

尝试的方法:

    Class myClass
    {
        private SerialPort _port; //Assume configured and connected.

        public void WaitFor(byte[] buffer)
        {            
            int bufferLength = buffer.Length;
            byte[] comparisonBuffer = new byte[bufferLength];

            while(true)
            {
                if(_port.BytesToRead >= bufferLength)
                {
                    _port.Read(comparisonBuffer, 0, bufferLength);
                    if (comparisonBuffer.SequenceEqual(buffer)) { return; }
                }
            }
        }
     {

我在这方面取得了相当大的成功,但它只是有一种“hacky”的感觉。它经常给我带来麻烦。我相信这是因为我无法保证在预期数据包之前或之后都没有收到其他数据,所以自然而然地,这种方法最终可能会不同步地读取流。在这种情况下,我不想丢失前导/尾随数据,但该方法应该释放线程。

我需要以程序化的方式实现,因此事件驱动的方法对我来说并不适用。在一般意义上,我希望能够实现为;

    Do thing;
    WaitFor(mybuffer);
    Do other thing;

最佳答案

SerialPort.Read() 已经阻塞,直到至少一个字节到达。因此,您不需要(也不应该)像现在这样使用 BytesToRead - 您已经引入了一个可怕的忙等待循环。

相反,做这样的事情:

// Reads 'count' bytes from a serial port into the specified
// part of a buffer. This blocks until all the bytes have been read.

public void BlockingRead(SerialPort port, byte[] buffer, int offset, int count)
{
    while (count > 0)
    {
        // SerialPort.Read() blocks until at least one byte has been read, or SerialPort.ReadTimeout milliseconds
        // have elapsed. If a timeout occurs a TimeoutException will be thrown.
        // Because SerialPort.Read() blocks until some data is available this is not a busy loop,
        // and we do NOT need to issue any calls to Thread.Sleep().

        int bytesRead = port.Read(buffer, offset, count);
        offset += bytesRead;
        count -= bytesRead;
    }
}

以下是根据 BlockingRead() 实现原始代码的方式:

public void WaitFor(SerialPort port, byte[] buffer)
{
    byte[] comparisonBuffer = new byte[buffer.Length];

    while (true)
    {
        BlockingRead(port, comparisonBuffer, 0, comparisonBuffer.Length);

        if (comparisonBuffer.SequenceEqual(buffer))
            return;
    }
}

关于c# - WaitFor() - 如何等待特定缓冲区到达 Steam/SerialPort?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39329448/

相关文章:

c# - 按照简单模式初始化 N 个数字数组的最简单方法是什么?

c# - 自动设置子项目的父引用

c# - 从外部服务流式传输视频

stream - 读取字节忽略 SBCL 灰色流中的 eof-error-p

stream - C-SPARQL 查询 - 精确匹配字符串文字

c - ansi c 是否允许在 rs232 零调制解调器上进行串行通信?

windows - CloseHandle() 在串口实际关闭之前返回

c# - Azure B2C 身份提供商登录失败 : AADB2C99002: User does not exist

c# - 如何创建自己的数据类型?

linux - 使用 perl 向调制解调器发送 AT 命令