What is the purpose of the SerialPort write buffer?
From outside SerialPort object, it seems to make no difference what the size of the开发者_开发问答 write buffer is, and whether or not it is full.
Using synchronous writing, the write method blocks until all the data has been sent and the buffer is empty.
Using async writing, the data is queued and the program continues on going. The callback method is not called until the write operation is completed and the data is out of the buffer.
The behavior of the serialport object seems to be the same regardless of how much data is in the buffer and whether or not the buffer is full. No errors seem to happen when the write buffer is full.
So, why be able to check BytesToWrite and WriteBufferSize at all? Is there any way that SerialPort behaves differently when the write buffer is full?
Buffers are a mechanism designed to allow whoever processes the buffer to do it in their own way, at their own time. When i send data, i want it to be pushed at the maximal rate of the port, but i don't want to busywait on the port and wait for each byte to be sent before i push the next one. So you have a processing buffer that feeds the hardware, and can be passed in chunks.
As for the why you'd want to check the BytesToWrite - you are often interested to know if all your data was sent before moving on to the next thing you want to do, you might expect a response after a given period of time, you might want to know what the actual transfer rate is etc'.
The C# SerialPort.BytesToWrite
property corresponds to the unmanaged Win32 COMSTAT.cbOutQue
field which is described as:
- The number of bytes of user data remaining to be transmitted for all write operations. This value will be zero for a nonoverlapped write.
This seems to suggest you could observe the write buffer being consumed as it is sent with async writing before the write complete callback is called.
I wanted to create a test utility that constantly sends out 0xAA out the serial port, with no gaps, forever. I don't care about RX.
I used a timer to keep the buffer full, and monitored BytesToWrite to wait below it was below threshold, before I wrote more data into the buffer.
I could have alternatively not used a timer, but refreshed the serial port in the AsyncCallback, but I wanted to do it this way for fun. You can view the label11 to see the buffer fill and empty.
Note you can get away with BeginWrite without EndWrite for a short time, but eventually you will run out resources. I am basically just putting in a dummy 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);
}
}
精彩评论