3

从 SerialPort 对象的外部来看,写入缓冲区的大小以及是否已满似乎没有区别。

使用同步写入,write 方法会阻塞,直到所有数据都发送完毕并且缓冲区为空。

使用异步写入,数据排队,程序继续运行。直到写操作完成并且数据超出缓冲区时才会调用回调方法。

无论缓冲区中有多少数据以及缓冲区是否已满,串行端口对象的行为似乎都是相同的。当写入缓冲区已满时,似乎没有发生错误。

那么,为什么能够检查 BytesToWrite 和 WriteBufferSize 呢?当写入缓冲区已满时,SerialPort 的行为有什么不同吗?

4

3 回答 3

1

缓冲区是一种机制,旨在允许处理缓冲区的任何人在自己的时间以自己的方式进行处理。当我发送数据时,我希望它以端口的最大速率推送,但我不想在端口上忙着等待,并在推送下一个字节之前等待发送每个字节。因此,您有一个为硬件提供数据的处理缓冲区,并且可以分块传递。

至于您为什么要检查 BytesToWrite - 您通常有兴趣知道在继续您想做的下一件事情之前是否发送了所有数据,您可能希望在给定的时间段后得到响应,您可能想知道实际的传输率是多少等'。

于 2011-04-20T00:20:46.807 回答
1

C#SerialPort.BytesToWrite属性对应于COMSTAT.cbOutQue描述为的非托管 Win32 字段:

  • 对于所有写操作,剩余要传输的用户数据字节数。对于非重叠写入,该值为零。

这似乎表明您可以观察到写入缓冲区正在被消耗,因为它是在调用写入完成回调之前通过异步写入发送的。

于 2011-04-20T00:21:02.247 回答
0

我想创建一个测试实用程序,它可以不断地从串行端口发送 0xAA,没有间隙,永远。我不在乎RX。

在我将更多数据写入缓冲区之前,我使用了一个计时器来保持缓冲区满,并监控 BytesToWrite 等待低于阈值。

我也可以不使用计时器,而是刷新 AsyncCallback 中的串行端口,但我想这样做是为了好玩。您可以查看 label11 以查看缓冲区的填充和清空。

请注意,您可以在短时间内在没有 EndWrite 的情况下使用 BeginWrite,但最终您将耗尽资源。我基本上只是放入一个虚拟的 EndWrite。

    private void checkBox2_CheckedChanged(object sender, EventArgs e)
    {
        timerFill.Enabled = checkBox2.Checked;
    }

    private void timerFill_Tick(object sender, EventArgs e)
    {
        GenerateSquareWave();
    }

    int const bufferSize = 256;

    void GenerateSquareWave()
    {
        int k = serialPort1.BytesToWrite;
        label11.Text = k.ToString();
        if (k < bufferSize)
        {
            byte[] data = new byte[bufferSize];
            for (int i = 0; i < bufferSize; i++)
            {
                data[i] = 0xAA;
            }
            serialPort1.BaseStream.BeginWrite(data, 0, data.Length, new AsyncCallback((IAsyncResult ar) => serialPort1.BaseStream.EndWrite(ar)), null);
        }
    }
于 2011-08-09T21:48:06.297 回答