SerialPort写缓冲区的目的是什么?

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

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

使用异步写入,数据排队,程序继续运行。 在写操作完成且数据超出缓冲区之前,不会调用回调方法。

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

那么,为什么能够检查BytesToWrite和WriteBufferSize呢? 当写缓冲区已满时,SerialPort是否有任何不同的行为方式?

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

至于你想要检查BytesToWrite的原因 – 你经常有兴趣知道你是否已经发送了所有数据,然后再转到你想要做的下一件事,你可能会在一段时间之后得到一个回复​​,你可能想知道实际转移率是多少等等。

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

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

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

我想创建一个测试实用程序,它不断地从串口发送出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); } }