C#多线程的问题!比较复杂!望大神指点!

zhu071011 2012-03-30 05:16:44
情况是这样的,这是代码

port.DataReceived += comm_DataReceived;//注册接受串口数据的事件,意思是只要串口有数据来,就触发响应函数

}
void comm_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
MethodInvoker dataremi = new MethodInvoker(updatemainlable);//异步形式,为了能访问父进程的控件
IAsyncResult iar=BeginInvoke(dataremi);//开始
Thread.sleep(1000); //没这句话,UI界面停止更新。疑问之处。
if (iar.IsCompleted)//判断串口数据接受的线程有没有执行好,好了就做下面的
{
outoffcontrol();//看看采集来的数值是否超标
savedata();//将采集来的数据存入数据库
}
}

功能实现的非常好!没有问题。但是当我想要看看整个程序的性能时。问题就来了。这程序在不断的创建新的线程,几分钟就能创建700多个线程。
经过排查,发现只要在 comm_DataReceived 函数里出现Thread.sleep(1000); ,那么就会出现不停创建新线程的情况。
但是没有Thread.sleep(1000); 这条语句的话,程序就一直循环在updatemainlable函数的开头到Application.DoEvents();这条语句。造成该线程无法进行下去,界面的数据无法更新。

所以想问问大神们,这是为什么?为什么在这样的函数里面不能有Thread.sleep这句话?
...全文
224 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
wy811007 2012-04-09
  • 打赏
  • 举报
回复
啊哦. 多线程很郁闷 我来学习下
我有个程序用了backgroundworker 读取几M 或几百M的txt文件 就会卡死 纠结啊
血痕123456 2012-04-09
  • 打赏
  • 举报
回复
没有看懂这个··········
  • 打赏
  • 举报
回复
最忌讳地就是轻易写出阻塞父线程结束的语句 --> 最忌讳地就是轻易写出阻塞父线程的执行方法结束的语句


这里问题的关键不是Thread.Sleep,它只是让阻塞之后的程序变得性能更差、逻辑更糟。导火索还是if(iar.IsCompleted)这类语句的问题。
  • 打赏
  • 举报
回复
如果不怕麻烦,可以尝试使用一两回 backgroundworker。这个机制比较“规范”。虽然有些繁琐。

你的comm_DataReceived方法中应该仅仅启动一个工作线程,而注册之后不用等线程实际开始,comm_DataReceived方法本身就应该结束了。所以这个方法执行起来瞬间就完了,然后主线程才可以去处理显示。

if(iar.IsCompleted) 这类语句阻塞了主线程。你其实使用了一个异步编程的语句,却在做模拟同步程序、进行阻塞的事情。所以异步编程时,最忌讳地就是轻易写出阻塞父线程结束的语句。



aa6103848252 2012-04-08
  • 打赏
  • 举报
回复
Form.Invoke()在其他线程里直接调用就行了,具体查下MSDN吧
aa6103848252 2012-03-30
  • 打赏
  • 举报
回复
BeginInvoke是异步的,他有个回调参数callback,传入AsyncCallback就行了,注意如果是访问UI线程要Form.Invoke()
zhu071011 2012-03-30
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]

使用 AsyncCallback
[/Quote]
谢谢提醒!小的这就去研究这个!
zhu071011 2012-03-30
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]

BeginInvoke本身是用线程池来实现的,如果你用sleep,那么当前的处理线程就会被阻塞,那么当下一次接收到数据时,由于线程池中的上个线程被阻塞,那么当前就没有可以使用的线程,那么线程池就会再创建新的线程,以至于几分钟就能创建700多个线程。
“但是没有Thread.sleep(1000); 这条语句的话,程序就一直循环在updatemainlable函数的开头到Application.……
[/Quote]
多谢大神们提醒!!!!!!真心醍醐灌顶啊!原来是这样!我去好好研究这个callBack!
rczjp 2012-03-30
  • 打赏
  • 举报
回复
使用 AsyncCallback
边城的刀声 2012-03-30
  • 打赏
  • 举报
回复
BeginInvoke本身是用线程池来实现的,如果你用sleep,那么当前的处理线程就会被阻塞,那么当下一次接收到数据时,由于线程池中的上个线程被阻塞,那么当前就没有可以使用的线程,那么线程池就会再创建新的线程,以至于几分钟就能创建700多个线程。
“但是没有Thread.sleep(1000); 这条语句的话,程序就一直循环在updatemainlable函数的开头到Application.DoEvents();这条语句。造成该线程无法进行下去,界面的数据无法更新。”
别用sleep这种方式,给BeginInvoke方法中传递 callBack
zhu071011 2012-03-30
  • 打赏
  • 举报
回复
哎呀!我来顶一下!!!!

111,126

社区成员

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

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

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