I made a code to send a message and get the answer asynchronously using a serial port
class Foo
{
SerialPort port;
private List<byte> RxedData;
public Foo(SerialPort sp)
{
sp.DataReceived += Data_Rx;
port = sp;
}
public bool Send(in byte[] tx, int rx, int timeout_ms = 100, int retry = 0)
{
AsyncPortFlush();
port.Write(tx, 0, tx.Length);
while (!AsyncPortRead(timeout_ms, rx))
{
if(retry --> 0)
{
AsyncPortFlush();
port.Write(tx, 0, tx.Length);
}
else return false;
}
return true;
}
private bool AsyncPortRead(int timeout_ms, int nbOfBytes)
{
Thread.Sleep(timeout_ms);
return RxedData.Count >= nbOfBytes;
}
private void AsyncPortFlush()
{
if (RxedData == null) RxedData = new List<byte>();
else RxedData.Clear();
}
private void Data_Rx(object sender, SerialDataReceivedEventArgs e)
{
if (sender is SerialPort self && self.IsOpen)
while (self.BytesToRead > 0) RxedData.Add((byte)self.ReadByte());
}
}
My issue is that sometimes I miss completely the answer, I checked hardware wise with a logic analyzer and I do get the answer, I still need to check if it gets to windows with wireshark but I suppose there no issue on this side
Do you have any idea why I'm missing the answer ?
I heard there are sometimes issues with the DataReceived
event. As Hans Passant stated in his comment, the event is invoked on another thread and probably you have some issues because your list is not thread-safe. Maybe you can try to write your code without the event?
private bool AsyncPortRead(int timeout_ms, int nbOfBytes)
{
try
{
port.ReadTimeout = timeout_ms;
byte[] data = new byte[nbOfBytes];
int receivedBytes = port.Read(data, 0, data.Length);
return receivedBytes == nbOfBytes;
}
catch (TimeoutException)
{
return false;
}
}