C# SerialPort写入缓冲区的用途是什么?

C# SerialPort写入缓冲区的用途是什么?,c#,serial-port,buffer,output-buffering,C#,Serial Port,Buffer,Output Buffering,从SerialPort对象外部看,写入缓冲区的大小以及是否已满似乎没有区别 使用同步写入,写入方法将阻塞,直到所有数据都已发送且缓冲区为空 使用异步写入,数据排队,程序继续运行。在写操作完成且数据超出缓冲区之前,不会调用回调方法 不管缓冲区中有多少数据以及缓冲区是否已满,serialport对象的行为似乎是相同的。写入缓冲区已满时,似乎不会发生错误 那么,为什么能够通过testowrite和WriteBufferSize检查呢?当写缓冲区已满时,SerialPort是否有不同的行为方式?缓冲区是

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

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

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

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


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

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

至于为什么要检查BytesToWrite,您通常想知道在进行下一步操作之前是否发送了所有数据,您可能希望在给定的时间段后收到响应,您可能想知道实际传输速率是多少等等

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

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

这似乎表明,在调用写完成回调之前,您可以在异步写入时观察写入缓冲区的使用情况。

我想创建一个测试实用程序,该实用程序可以一直将0xAA发送到串行端口,而不留任何间隙。我不在乎RX

我使用了一个计时器来保持缓冲区满,并通过Testowrite进行监视,在将更多数据写入缓冲区之前,在低于阈值的情况下等待

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

注意,您可以在短时间内不使用EndWrite而使用BeginWrite,但最终会耗尽资源。我基本上只是在写一个虚拟的尾端

    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);
        }
    }
private void checkBox2\u CheckedChanged(对象发送方,事件参数e)
{
timerFill.Enabled=复选框2.选中;
}
私有void timerFill_Tick(对象发送方,事件参数e)
{
生成方波();
}
int const bufferSize=256;
void生成方波()
{
int k=serialPort1.BytesToWrite;
label11.Text=k.ToString();
if(kserialPort1.BaseStream.EndWrite(ar)),null);
}
}

BytesToWrite属性与缓冲区大小无关?BytesToWrite可以是缓冲区大小的一半或两倍,这并不意味着缓冲区已满或未满?不,BytesToWrite是尚未写入串行端口的字节数。根据文档,它表示发送缓冲区中的字节数,因此它可以是缓冲区大小的一半,但绝不是两倍。写入缓冲区与调用write方法时传递的数据不同。底层win32实现使用缓冲区与实际端口通信。抽象(c#中的写入方法)处理较长(或更小)端口的分段和传输好的,这就是我困惑的地方——写缓冲区是2k,但我可以异步写100k,BytesToWrite会告诉我100000,即使WriteBufferSize只有2048。在发送字节时,我可以看到它倒计时到0,但无论缓冲区有多满,程序的行为都是一样的。这正是我所想的,只是我可以在缓冲区满后继续写入数据,并且不会丢失任何数据,也不会抛出错误。我忘了回答你的其余问题
SerialPort.WriteBufferSize
对应于
SetupComm(…,dwOutQueue)
,它被记录为设备驱动程序可以自由忽略的建议缓冲区大小:我明白了。在文档中,它说它可以自由使用任何I/O缓冲方案,这意味着它可能有某种自适应缓冲区或其他东西。我将看看在“队列”崩溃之前我可以写入多少字节:)这意味着不超过您自己的缓冲区大小是明智的,但实际上,如果您使用的是库存硬件和Microsoft驱动程序,则是无害的。明白了--我想如果BytesToWrite>=WriteBufferSize,我可以假设缓冲区已满。谢谢