英文:
C# serial port missing answer
问题
以下是代码部分的翻译:
我编写了一段代码,用串口异步发送消息并获取答复
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());
}
}
至于您的问题,您提到有时会完全错过答复。您已经通过逻辑分析仪硬件方面检查并确认收到答复,但您还需要通过Wireshark检查它是否传递到Windows。有可能在代码中存在一些问题,导致您错过答复。您可以检查以下几个方面:
-
超时设置:您的
Send
方法中使用了AsyncPortRead
来等待答复。确保timeout_ms
参数足够长,以便允许足够的时间来接收答复。 -
异常处理:检查是否在串口通信中发生了异常,并确保适当地处理异常情况。
-
数据处理:确保接收的数据按照预期进行处理,以便正确识别答复。您可能需要验证接收的数据是否与您期望的一致。
-
重试机制:如果未成功接收答复,您的代码中有一个重试机制。确保重试逻辑正常工作并且不会导致死循环或其他问题。
根据这些建议,您可以尝试调试和改进您的代码以确定为什么有时会错过答复。
英文:
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 ?
答案1
得分: 1
我听说DataReceived
事件有时会出现问题。正如Hans Passant在他的评论中所说,该事件在另一个线程上调用,可能是因为你的列表不是线程安全的,所以可能会出现一些问题。也许你可以尝试在没有事件的情况下编写代码?
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;
}
}
英文:
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;
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论