从SerialPort对象的外部看,写缓冲区的大小以及它是否已满是没有区别的。
使用同步写入,write方法将阻塞,直到所有数据都已发送且缓冲区为空。
使用异步写入,数据排队,程序继续运行。在写操作完成且数据超出缓冲区之前,不会调用回调方法。
无论缓冲区中有多少数据以及缓冲区是否已满,serialport对象的行为似乎都是相同的。写缓冲区已满时,似乎没有错误发生。
那么,为什么能够检查BytesToWrite和WriteBufferSize呢?当写缓冲区已满时,SerialPort有什么不同的行为吗?
答案 0 :(得分:1)
缓冲区是一种机制,旨在允许任何处理缓冲区的人在自己的时间以自己的方式执行此操作。 当我发送数据时,我希望它以端口的最大速率被推送,但我不想在端口上忙等待并等待每个字节在我推送下一个字节之前发送。因此,您有一个处理缓冲区,可以为硬件提供数据,并且可以以块的形式传递。
至于你想要检查BytesToWrite的原因 - 你经常有兴趣知道你的所有数据是否都已发送,然后再转到你想做的下一件事,你可能会在给定的一段时间之后得到回应。时间,你可能想知道实际的转移率是什么等。
答案 1 :(得分:1)
C#SerialPort.BytesToWrite
属性对应于非托管Win32 COMSTAT.cbOutQue
字段,该字段描述为:
这似乎表明你可以观察到在写入完整回调被调用之前使用异步写入发送的写缓冲区。
答案 2 :(得分: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);
}
}