C#串口接收函数多线程的问题

xaabeijixiong2012 2012-07-11 10:08:38
这个问题困扰了我两天,全程利用RS232短接引脚自发自收:

CSDN提示没没有分来提这个问题,我都不知道能不能提出来这个问题

我做了2件事:
第一件:定义了一个串口接收函数:
void comm_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
buf = new byte[n];//声明一个临时数组存储当前来的串口数据
comm.Read(buf, 0, n);//读取缓冲数据
}
第二件事:定义了一个串口自动发送函数:
private void timer1_Tick(object sender, EventArgs e)
{
System.Timers.Timer time2 = new System.Timers.Timer();
time2.Interval = 5;//时钟的间隔为100ms
if (comm.IsOpen)
{
qufen = 0;
string ComString = "12 34 56 78 90 AB CD EF";
int len = ComString.Length / 2;
byte[] bytesend = HexStringToByteArray(ComString);(将string转为byte数组,公式是正确的,我看过)
comm.Write(bytesend, 0, bytesend.Length);
time2.Start();//时间开始启动
DateTime dtnow = DateTime.Now;

while (true)
{
DateTime dtend = DateTime.Now;
System.TimeSpan ts = dtend - dtnow;
int a = Convert.ToInt32(ts.TotalMilliseconds);
if (comm.BytesToRead == 8 || a >= 30)
{
time2.Stop();
break;
}
else
{
Thread.Sleep(1);
}
}
int n = comm.BytesToRead;
comm_DataReceived(null, null);
}
}

全程单步执行,利用串口监视工具全程严格监视:
单步执行,发现如下:
1)第一个发送周期:发送和接收全部在上述代码中蓝色的代码处(分别对应于write和read)发生,全部为正确;
2)第二个发送周期:发送在上述代码中蓝色代码处(对应于write)发生,为正确;但是接收却发生在上述代码中的红色代码处(time2.Start();或者 DateTime dtnow = DateTime.Now;处);
这是为什么???我根本没有给它read的命令!!它为什么自己会读上来????导致我后续的comm_DataReceived(null, null)调用接收函数时却没有东西可收!!!!!,这到底是为什么!!!!!!3)第三个发送周期:同第一个周期;
4)第四个发送周期:同第二个周期;
......以此类推

上述情况是为什么?》????????????????????????

有人说这是不同的线程触发的:就是DataReceive是一个辅线程,在主线程触发发送时,数据已经收到,DataReceive函数就会自动触发(在while循环执行的时候就触发接收了),用不着在后面调用comm_DataReceived(null, null)来做多余的操作;

上面的解释对于偶数次(第二个发送周期、第四个发送周期......)好像是对的,但是如果是这样的话,我反问一句:那为什么奇数次发送周期(第一次发送周期、第三次发送周期......)却没有自动触发接收,一定要等到我通过comm_DataReceived(null, null)调用接收函数的时候才会真正的触发接收呢??? 这不是自相矛盾吗?????

这个问题应该是一个多线程处理的问题。
我是一个新手,
请高手务必就事论事,就我的程序来发表意见,不要给一个单词,一句话!!!您是高手,我承认,但您简单的说一句话、一个单词,小弟我是真的真的真的真的真的真的看不懂!!!!!!!!!!!!!!!!!!!!!!!!


我最终想达到稳定接收的目的:就是想让它什么时候接收,就什么时候接收;什么时候清空,就什么时候清空!!!!!!

麻烦给出修改程序的建议 谢谢!!!!!
...全文
732 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
Saleayas 2012-07-11
  • 打赏
  • 举报
回复
如果你需要一个这样的处理:
发送命令---外设接受---外设处理---外设写回---读取命令。

不需要任何额外的处理。
void F()
{
Send(...);
Recv(...);
}
其中 在没有进入 F 的时候,串口是没有数据接受的,否则就错误了。
此时也不需要订阅 DataReceived 事件。
Recv 需要处理超时。
Send和Recv 都需要处理断开错误。
Recv 需要一直等待,直到读取到期望的数据。或者断开外设或者超时。
xaabeijixiong2012 2012-07-11
  • 打赏
  • 举报
回复
“你在使用快递的时候,你可以决定什么时候发快件,你能决定什么时候收吗?
必须等快递员通知你,这就是 DataReceived。
当然你也可以一直在等着。”

嗯有点这个意思

我补充下:一个简单的串口确实不需要timer,但是我要的功能是:在一个中断周期内才会将命令发出去,故需要一个timer1;
发完后需要等待其回复我,就用了一个while循环,这个while循环的跳出有2个条件(一个是串口收到的字节数到了,另一个是超时了),然后为了避免while循环死锁,就用了timer2来给它超时的时间来跳出;

好了,补充完毕

但是上述的快递员的收发好像确实有这个意思,但是我还是不能结合到我的程序上来

为什么在单步调试的情况下,自发自收,奇数次发送周期里,发完了之后,DataReceive不会自动触发,要我用DataReceive(null,null)来调用,它才会去读;
但是在偶数次发送周期里,只要我发完了之后,随便走下面的一条或二条命令,DataReceive就自动触发了,并将串口内的东西读了上来

为什么同样的程序在不同的执行次数下,会有不同的结果?
Saleayas 2012-07-11
  • 打赏
  • 举报
回复
你在使用快递的时候,你可以决定什么时候发快件,你能决定什么时候收吗?
必须等快递员通知你,这就是 DataReceived。
当然你也可以一直在等着。
book_freeboy827 2012-07-11
  • 打赏
  • 举报
回复
一个周期处理完再发送数据试试
xaabeijixiong2012 2012-07-11
  • 打赏
  • 举报
回复
借用Saleayas的回复“如果 comm_DataReceived 是串口的 DataReceived 回调。
那么这个是自动被叫的。”

那我想问你,为什么奇数次发送周期在发送后,它没有自动触发??
Saleayas 2012-07-11
  • 打赏
  • 举报
回复
而且一个破串口需要使用 Timer 这么复杂吗?
Saleayas 2012-07-11
  • 打赏
  • 举报
回复
如果 comm_DataReceived 是串口的 DataReceived 回调。
那么这个是自动被叫的。
xaabeijixiong2012 2012-07-11
  • 打赏
  • 举报
回复
CSDN上没有高手吗
xaabeijixiong2012 2012-07-11
  • 打赏
  • 举报
回复
time2是一个时钟,为了避免while循环死锁,我做了这么一个东西
while循环跳出的条件是(串口缓存区数据是都达到8字节||(或者)while循环的时间是否超过30ms)

还有我确定每次都收完了!!!

现在的问题是为什么同样的程序单步执行,奇数次周期发送和接收全部在write和read命令时执行,而偶数次周期的接收却是在write之后就自动进行了,我根本就没有给它read命令!!!!!!
导致我真正的read命令到时,没东西可读!!!

这到底是为什么??

真的是欲哭无泪啊

感谢bdmh的热心回复,不过您的回复好像没有帮到我,并没有给出问题的根源在哪里?


我将本帖子加到100分,将全部给能够帮我解答我的这个问题的人!!
我的问题详见上面的帖子!!!
bdmh 2012-07-11
  • 打赏
  • 举报
回复
两点
看看每次发送的内容是否一次就接受完了,是不是会导致接收两次,每次接收不全

time2是干吗的,里面是否控制了窗口
Saleayas 2012-07-11
  • 打赏
  • 举报
回复
这和你写一个磁盘文件类似。
需要看你这么处理这些问题。
单线程不是慢的问题。而是UI线程的响应问题。
xaabeijixiong2012 2012-07-11
  • 打赏
  • 举报
回复
非常感谢Saleayas的热心回复,问题基本上解决了

但还是有一个问题:
我丢弃了DataReceive函数,就意味着我的程序必须要走单线程这条路,

而单线程这条路会比多线程要慢多少呢??
是慢很多还是慢的还可以??

多线程实在不会处理

110,571

社区成员

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

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

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