Your timer should not be necessary, and let port.RecievedBytesThrescold=1 (default). The only thing you can be sure of if you set it to 21, is that it will be at least 21 long. My suggestion is to do the buffering your self:
byte[] buffer = new byte[50];
int endOfBuffer = 0;
void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
int dataLength = _serialPort.BytesToRead;
byte[] data = new byte[dataLength];
int nbrDataRead = _serialPort.Read(data, 0, dataLength);
if (nbrDataRead == 0)
return;
Buffer.BlockCopy(data, 0, buffer, endOfBuffer, nbrDataRead);
endOfBuffer += nbrDataRead;
if(endOfBuffer >= 21)
{
byte[] plcDataArray = new byte[21];
Buffer.BlockCopy(buffer, 0, plcDataArray, 0, 21);
endOfBuffer -= 21;
if(endOfBuffer != 0)
Buffer.BlockCopy(buffer, 0, buffer, 21, endOfBuffer);
if(SignalCompletePackageEvent != null)
SignalCompletePackageEvent(this, EventArgsTakingYourByteArray(plcDataArray));
}
}
I have shared a very simple serial port app, and you're free to look at it
Basic serial port listening application.
Good luck. NB: Always happy if you vote on the solution ;)