C#串口读数据DataReceived监听不能快速反应

gx404965618 2016-06-21 09:51:26
各位老师同仁大家好,我是一个新手,今天学习C#串口时候碰到了一个问题,还望大家指导,先谢谢了。
具体问题我在windowsForm中用一个Button控件点击一下发送数据,用TEXTBOX显示读取的下位机数据。但是问我发现SerialPort中的监听事件DataReceived反应不够积极,有时候Button点一次TEXTBOX有数据,有时候点多次才有数据。跟踪了一下DataReceived发现有时候可以进到事件中,有时候进不去。
不知道我描述的问题是否清楚,再一次感谢大家的指导,代码如下:
public static void Send_Data()
{
byte[] B = new byte[3] { 0x4d, 0x30, 0x0d };
Com_Port.Write(B, 0, 3);
}


private static void Com_Port_DataReceived(object sender ,SerialDataReceivedEventArgs e)
{
Thread _readThread;
_readThread=new Thread (str_Recive);
_readThread.Start();
}
public static void str_Recive()
{

if (Com_Port.IsOpen == true)
{
byte[] readByte = new byte[Com_Port.ReadBufferSize];
int count = Com_Port.Read(readByte, 0, Com_Port.ReadBufferSize);
strbuffer = System.Text.Encoding.ASCII.GetString(readByte, 0, count);

}

else
{
TimeSpan waitetime = new TimeSpan(0, 0, 0, 50);
Thread.Sleep(waitetime);
}
}
...全文
546 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
黑娃 2016-06-22
  • 打赏
  • 举报
回复
Com_Port_DataReceived 这个函数是事件响应触发的,本来就是不同线程了,不要再这个基础上再开线程去接收数据
神探布杰 2016-06-22
  • 打赏
  • 举报
回复
再补充 如果你想任意长短的信息都接收到,最好不要用事件,自己写一个循环来调用SerialPort1 .ReadExisting()
神探布杰 2016-06-22
  • 打赏
  • 举报
回复

串口组件需要接收一定 字节数才会触发DataReceived事件,检查一下这个属性值
龍过鸡年 2016-06-22
  • 打赏
  • 举报
回复
引用 14 楼 gx404965618 的回复:
老师 if (e.EventType == System.IO.Ports.SerialData.Eof)这句话的含义是什么?这个List<byte> data = new List<byte>(); 为什么要全局变量?因为是新手所以不懂,忘解答,谢谢!
System.IO.Ports.SerialData 枚举的说明 https://msdn.microsoft.com/zh-cn/library/system.io.ports.serialdata(v=vs.100).aspx SerialPort.DataReceived 事件的说明 https://msdn.microsoft.com/zh-cn/library/system.io.ports.serialport.datareceived(v=vs.100).aspx 这都是 MSDN 的资料,仔细看备注
gx404965618 2016-06-22
  • 打赏
  • 举报
回复
引用 12 楼 qqamoon 的回复:
[quote=引用 7 楼 gx404965618 的回复:] 首先感谢各位老师的回复,现在主要的问题还是监听反应不够积极。 Com_Port.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived); 我点击Button后 ,串口数据已经发送出去 ,我在监听里面设置断点监视,我要连续点击多次Button才能监控进入到串口监听里面去,我想实现的功能是点一下Button在TextBox中就能够显示读取的内容,代码如下:谢谢 private void button1_Click(object sender, EventArgs e) { Comport.Send_Data(); } 发送代码: public static void Send_Data() { //Com_Port.ReceivedBytesThreshold = 1; byte[] B = new byte[3] { 0x4d, 0x30, 0x0d }; Com_Port.Write(B, 0, 3); } 监听程序: private static void sp_DataReceived(object sender, SerialDataReceivedEventArgs e) { _readaFlag = false; List<byte> data = new List<byte>(); //SerialPort sp = (SerialPort)sender; byte[] buffer = new byte[Com_Port.BytesToRead]; int lenght = Com_Port.Read(buffer, 0, buffer.Length); data.AddRange(buffer); strbuffer = (Encoding.Default.GetString(data.ToArray())); data.Clear(); }
List<byte> data = new List<byte>(); 这是全局对象,不要放在 DataReceived 中。 [/quote] 老师 if (e.EventType == System.IO.Ports.SerialData.Eof)这句话的含义是什么?这个List<byte> data = new List<byte>(); 为什么要全局变量?因为是新手所以不懂,忘解答,谢谢!
gx404965618 2016-06-22
  • 打赏
  • 举报
回复
引用 11 楼 falcomavin 的回复:
[quote=引用 10 楼 gx404965618 的回复:] 我想问问各位老师,下位机本身的问题会导致监听不及时吗?我开始用的是激光位移传感器做实验,出现了串口监听程序进入不积极,我索性换了PLC做下位机,我断点调试时每次都可以进去。所以有疑问还忘各位老师指点,很纠结啊!
你这个说法不对,不叫监听不及时,人家一直都在监听,问题出在下位机没有及时响应。你为什么不用串口调试助手试一下,是不是及时收到下位机答复,一目了然[/quote] 我用串口调试助手调试过,不是很顺畅,所以可以确定是下位机的原因!
龍过鸡年 2016-06-22
  • 打赏
  • 举报
回复
引用 7 楼 gx404965618 的回复:
首先感谢各位老师的回复,现在主要的问题还是监听反应不够积极。 Com_Port.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived); 我点击Button后 ,串口数据已经发送出去 ,我在监听里面设置断点监视,我要连续点击多次Button才能监控进入到串口监听里面去,我想实现的功能是点一下Button在TextBox中就能够显示读取的内容,代码如下:谢谢 private void button1_Click(object sender, EventArgs e) { Comport.Send_Data(); } 发送代码: public static void Send_Data() { //Com_Port.ReceivedBytesThreshold = 1; byte[] B = new byte[3] { 0x4d, 0x30, 0x0d }; Com_Port.Write(B, 0, 3); } 监听程序: private static void sp_DataReceived(object sender, SerialDataReceivedEventArgs e) { _readaFlag = false; List<byte> data = new List<byte>(); //SerialPort sp = (SerialPort)sender; byte[] buffer = new byte[Com_Port.BytesToRead]; int lenght = Com_Port.Read(buffer, 0, buffer.Length); data.AddRange(buffer); strbuffer = (Encoding.Default.GetString(data.ToArray())); data.Clear(); }
List<byte> data = new List<byte>(); 这是全局对象,不要放在 DataReceived 中。
黑娃 2016-06-22
  • 打赏
  • 举报
回复
引用 10 楼 gx404965618 的回复:
我想问问各位老师,下位机本身的问题会导致监听不及时吗?我开始用的是激光位移传感器做实验,出现了串口监听程序进入不积极,我索性换了PLC做下位机,我断点调试时每次都可以进去。所以有疑问还忘各位老师指点,很纠结啊!
你这个说法不对,不叫监听不及时,人家一直都在监听,问题出在下位机没有及时响应。你为什么不用串口调试助手试一下,是不是及时收到下位机答复,一目了然
gx404965618 2016-06-22
  • 打赏
  • 举报
回复
我想问问各位老师,下位机本身的问题会导致监听不及时吗?我开始用的是激光位移传感器做实验,出现了串口监听程序进入不积极,我索性换了PLC做下位机,我断点调试时每次都可以进去。所以有疑问还忘各位老师指点,很纠结啊!
gx404965618 2016-06-22
  • 打赏
  • 举报
回复
Com_Port.ReceivedBytesThreshold = 1;用了这个还是不行。
黑娃 2016-06-22
  • 打赏
  • 举报
回复
先确认你的下位机是否是即使回复的,可以用串口调试助手发指令试试。 如果是即使得,你看看串口对象里面有个属性,好像叫什么threshold,专门用来指示串口缓冲收到几个字节触发事件,把它设置成最小。
gx404965618 2016-06-22
  • 打赏
  • 举报
回复
首先感谢各位老师的回复,现在主要的问题还是监听反应不够积极。 Com_Port.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived); 我点击Button后 ,串口数据已经发送出去 ,我在监听里面设置断点监视,我要连续点击多次Button才能监控进入到串口监听里面去,我想实现的功能是点一下Button在TextBox中就能够显示读取的内容,代码如下:谢谢 private void button1_Click(object sender, EventArgs e) { Comport.Send_Data(); } 发送代码: public static void Send_Data() { //Com_Port.ReceivedBytesThreshold = 1; byte[] B = new byte[3] { 0x4d, 0x30, 0x0d }; Com_Port.Write(B, 0, 3); } 监听程序: private static void sp_DataReceived(object sender, SerialDataReceivedEventArgs e) { _readaFlag = false; List<byte> data = new List<byte>(); //SerialPort sp = (SerialPort)sender; byte[] buffer = new byte[Com_Port.BytesToRead]; int lenght = Com_Port.Read(buffer, 0, buffer.Length); data.AddRange(buffer); strbuffer = (Encoding.Default.GetString(data.ToArray())); data.Clear(); }
xian_wwq 2016-06-21
  • 打赏
  • 举报
回复
个人感觉是数据接收和解析没有分离导致效率低下 解决方案2楼已经说过了, 把数据解析放到线程池中去
  • 打赏
  • 举报
回复
如果你处理所收到的消息时需要异步子线程中处理,那么你可以在 Com_Port.Read 执行完毕之后才使用子线程来处理(建议你使用系统线程池,而不要 new Thead() 实例。虽然后者启动任务的速度快,但是它也不会优化系统)。 除了不要乱使用 Thread、不要动不动就 Encoding.GetString(你应该在确定收到完整的一个消息之后,再Encoding.GetString),写 Thead.Sleep(50) 也是匪夷所思的。既然你不应该接受,就什么都不干就好了,为什么要故意阻塞你的程序50毫秒?到底是哪根筋搭错了要写 Thread.Sleep(50)? 凡是在通讯接受代码中写 Sleep() 的,基本上都是坑爹的一些博客中看到的。我们在一些”示例“中也许为了测试模拟”耗时的操作“而写 Thread.Sleep(50),你的真实应用怎么能胡乱出现这种我们用来“模拟一个耗时操作”的代码?
龍过鸡年 2016-06-21
  • 打赏
  • 举报
回复
不需要在 DataReceived 事件里开线程 List<byte> data = new List<byte>(); private static void sp_DataReceived(object sender, SerialDataReceivedEventArgs e) { SerialPort sp = (SerialPort)sender; byte[] buffer = new byte[sp.BytesToRead]; int lenght = sp.Read(buffer, 0, buffer.Length); data.AddRange(buffer); if (e.EventType == System.IO.Ports.SerialData.Eof) // 很可能接收不到该标识 需要自己判断数据结束和开始位标识 { Console.WriteLine(Encoding.Default.GetString(data.ToArray())); data.Clear(); } }

110,571

社区成员

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

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

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