【求助】C#串口通信中,写了list缓冲处理数据后,订阅的事件不再执行

Leo_Cho 2018-02-04 07:16:02
小弟C#新人,写了一个串口通信程序,用来接收下位机传来的数据,之前写的程序没有使用list,直接读,虽说能用,但觉得不妥,这次使用了list缓冲,但是使用时发现,应该是只触发了一次事件,后面的数据都没有再处理显示了,不知道为什么,求助各位大神。
 private void Com_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
byte[] ReDatas = new byte[ComDevice.BytesToRead];
ComDevice.Read(ReDatas, 0, ReDatas.Length);//读取数据
queue.Enqueue(ReDatas);
while (queue.Find())
{
byte[] readBuffer = new byte[38];
readBuffer = queue.Dequeue();
this.AddData(readBuffer);//输出十六进制原数据,输出字符数据
if(readBuffer[1] == 0x63)
this.AddData_D1(readBuffer);//输出十进制数据
else if(readBuffer[1] == 0x72)
this.AddData_D2(readBuffer);//输出校正后的十进制数据
}

}

class bytequeue
{
private List<byte> m_buffer = new List<byte>();
public bool Find()
{
if (m_buffer.Count == 0)
return false;
int HeadIndex = m_buffer.FindIndex(o => o == 0x6D);

if (HeadIndex == -1)
{
m_buffer.Clear();
return false; //没找到m
}
else if (HeadIndex != 0) //移除帧头前的数据
{
if (HeadIndex > 1)
m_buffer.RemoveRange(0, HeadIndex );
}

int length = 38;

if (m_buffer.Count < length)
{
return false;
}

int TailIndex = m_buffer.FindIndex(o => o == 0x0A); //查找55的位置

if (TailIndex == -1)
{
//这一步为防止连发一个AA开头的包后,没发55,而又发了一个AA
int head = m_buffer.FindLastIndex(o => o == 0xAA);
if (head > -1)
{
m_buffer.RemoveRange(0, head );
}
return false;
}
else if (TailIndex + 1 != length ) //计算包尾是否与包长度相等
{
m_buffer.RemoveRange(0, TailIndex);
return false;
}

return true;
}


/// <summary>
/// 数据长度
/// </summary>
/// <returns></returns>
/*public int GetLength()
{

if (m_buffer.Count >= 3)
{
byte[] len = new byte[2];
len[0] = m_buffer[1];
len[1] = m_buffer[2];
return BitConverter.ToInt16(len, 0);
}
return 0;
}*/

/// <summary>
/// 命令码
/// </summary>
/// <returns></returns>
/*public byte Cmd()
{
if (m_buffer.Count >= 4)
{
return m_buffer[3];
}
return 0;
}*/


/// <summary>
/// 提取数据
/// </summary>
public byte[] Dequeue()
{
int size = 38;
//m_buffer.RemoveRange(0,1);
//m_buffer.RemoveRange(76,1);
byte[] buffer = m_buffer.Take(size).ToArray();
m_buffer.RemoveRange(0, size);
return buffer;
}

/// <summary>
/// 队列数据
/// </summary>
/// <param name="buffer"></param>
public void Enqueue(byte[] buffer)
{
m_buffer.AddRange(buffer);
}
}
}

应该是while循环处理完第一次触发时间的接收的数据后,就没有继续处理了,不知道怎么改了,求助各位
...全文
389 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
嗯,又看了一下你的复杂程序,你判断了 return false 然后退出循环。 那么对于 mc %02x %08x %08x %08x %08x %04x %02x %08x %c%d:%d\r\n mr %02x %08x %08x %08x %08x %04x %02x %04x%04x %c%d:%d\r\n 这种数据没能分解为两条消息,你其实完全可以自己调试,找 bug 了。用不着求人告诉你怎样编程,你应该自己单步调试,贴出有问题的调试画面来。
  • 打赏
  • 举报
回复
在 Com_DataReceived 中,直接把数据放到 buffer 中,然后查找是否存在第一个消息,如果不存在就直接结束了。怎么还 while、还 Dequeue 等等操作呢?
  • 打赏
  • 举报
回复
引用 7 楼 weixin_40818843 的回复:
[quote=引用 5 楼 From_TaiWan 的回复:] m_buffer.RemoveRange(0, size); ==> 改成m_buffer.RemoveRange(0, m_buffer.Count);
我试了一下,是可以的,但是有了新的问题,因为我接收的数据实际上是这样的 mc %02x %08x %08x %08x %08x %04x %02x %08x %c%d:%d\r\n mr %02x %08x %08x %08x %08x %04x %02x %04x%04x %c%d:%d\r\n 因为下位机是按char的格式发送的,所以我没法加上HEX的AA,55作为帧头帧尾,用的是m和换行,也就是6D和0A,用了您的方法过后,就解决了我的问题,但是这一行数据mr %02x %08x %08x %08x %08x %04x %02x %04x%04x %c%d:%d\r\n也被抹掉了,我就无法接收了,出现了新的问题。十分感谢您的答案,不知道有没有什么新的解决方案呢,例如如何加上不在有效数据位里的帧头帧尾或者其他方法[/quote] 数据既有可能粘包也有可能分包,你应该从buffer中查找第一条消息的回车换行结束符,然后取出第一条消息(留下剩下的内容)进行处理,不能抹掉剩下的数据。也可能根本找不到消息结尾,那么就应该等到下一次收到消息之后再查找,而不能抹掉数据。
Leo_Cho 2018-02-08
  • 打赏
  • 举报
回复
引用 5 楼 From_TaiWan 的回复:
m_buffer.RemoveRange(0, size); ==> 改成m_buffer.RemoveRange(0, m_buffer.Count);
我试了一下,是可以的,但是有了新的问题,因为我接收的数据实际上是这样的 mc %02x %08x %08x %08x %08x %04x %02x %08x %c%d:%d\r\n mr %02x %08x %08x %08x %08x %04x %02x %04x%04x %c%d:%d\r\n 因为下位机是按char的格式发送的,所以我没法加上HEX的AA,55作为帧头帧尾,用的是m和换行,也就是6D和0A,用了您的方法过后,就解决了我的问题,但是这一行数据mr %02x %08x %08x %08x %08x %04x %02x %04x%04x %c%d:%d\r\n也被抹掉了,我就无法接收了,出现了新的问题。十分感谢您的答案,不知道有没有什么新的解决方案呢,例如如何加上不在有效数据位里的帧头帧尾或者其他方法
Leo_Cho 2018-02-08
  • 打赏
  • 举报
回复
引用 6 楼 xuzuning 的回复:
虽然 queue 用的不妥,但并不是问题的原因 注意楼主 #2 的描述 打开串口,让下位机发送数据,可以正常使用 打开串口,让下位机发送数据,出毛病了 显然是丢失了数据帧头,造成数据无法解析
谢谢您的答案,有一点不能理解的是,就是出现问题的操作是可以显示处理一部分数据的,说明还是判断到了帧头,而且如果数据一直在持续发送,为什么会找不到帧头呢?
xuzuning 2018-02-08
  • 打赏
  • 举报
回复
虽然 queue 用的不妥,但并不是问题的原因 注意楼主 #2 的描述 打开串口,让下位机发送数据,可以正常使用 打开串口,让下位机发送数据,出毛病了 显然是丢失了数据帧头,造成数据无法解析
秋的红果实 2018-02-08
  • 打赏
  • 举报
回复
m_buffer.RemoveRange(0, size); ==> 改成m_buffer.RemoveRange(0, m_buffer.Count);
Leo_Cho 2018-02-07
  • 打赏
  • 举报
回复
引用 3 楼 Vblegend_2013 的回复:
queue不是这么用的吧? 这样用 queue一点意义都没有!哪怕你把queue.find用异步包裹一下也好!
请问那应该是怎么用的呢,用异步包裹是什么意思呢,不太明白
土豆赛叩 2018-02-05
  • 打赏
  • 举报
回复
queue不是这么用的吧? 这样用 queue一点意义都没有!哪怕你把queue.find用异步包裹一下也好!
Leo_Cho 2018-02-04
  • 打赏
  • 举报
回复
经过测试,当我先打开串口,然后再让下位机发送数据,我先写的收的这个软件,可以正常使用,更新数据,但是当我先开启下位机发送,然后打开上位机软件的串口时,就会出现我刚刚所描述的问题,读取处理一些值后,不像后开下位机那样持续更新接收处理了,不知道为什么会这样呢,求稳各位大神
Leo_Cho 2018-02-04
  • 打赏
  • 举报
回复
在想是不是要再开一个线程呢

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧