net下线程控制问题

airskys 2011-06-15 04:53:25
因为要做一个电机控制的系统,软件需要在后台开一个线程,不停的读取下位机数据和发送控制命令,命令发送和处理的时间都不会超过1毫秒。使用的vs2005,net2.0,语言是vb。net。
在开发过程中,我发现如果在后台的线程中不加入Application.doevent,或者Thread.sleep,那么程序就会假死,既界面过段时间就不能做任何反应了。而加入这两个功能造成我在时间控制上的不准确,我需要每5个毫秒发送一次数据,而这个5个毫秒的时间不能够得到精确的控制,有的时候甚至能长达40毫秒,这个是我系统不能够允许的。
可是我在VB下如果直接写一个函数执行就不会出现时间控制不准确的问题,而在net下按说有了线程控制会更加强大了,可线程的时间控制反倒不行。
各位仁兄有做过类似控制系统在net下的请帮忙指教下。
如何在net平台下线程应该如何操作才能够精确的控制程序运行的时间。
...全文
206 23 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
wenhu420 2011-10-21
  • 打赏
  • 举报
回复
你没有办法控制5m内完成程序,同时,还有很多应用程序抢占时间片,也不能保证5m内保证你能抢到时间片。我相信不一定在5m内数据都有变动,只需要对变动数据拉出来,这样不就快了吗?
airskys 2011-06-29
  • 打赏
  • 举报
回复
准备结贴,收获是有些,不过线程管理方面的经验还是没有获得多少,可能还是在实际工作中在锻炼吧
War3_Fan 2011-06-22
  • 打赏
  • 举报
回复
高手啊。 倾倒
jy251 2011-06-22
  • 打赏
  • 举报
回复
个人觉得啊,多线程是一定要用的,但是时间间隔5ms的话,又一个问题,并不是说CPU什么的,而是说你的程序在5ms的时间之内是否能执行完毕,如果不能执行完毕,那么如果你就只有一个线程,你的程序必定不能5ms一次的精准运行。

3楼给的东西很好,我仔细看了下,感觉并不是第一眼看到的时候所以为的那么简单,这个文章分析了begininvoke真实的运行线程,当做学习扩展可以看看,但是对于你的问题并不会又太大的帮助。

我的意见是,你既然每5ms运行一次程序,那么你就干脆直接使用delegate. begininvoke来做,每次调用都invoke一次,也就是说每5ms invoke一次,但是要注意你invoke的函数里面最好使用的是局部变量或者线程安全的变量。一个线程来执行5ms每次的操作,除非你的线程主体能在5ms之内执行完毕,否则还是多起几个线程吧,反正线程池里面的线程又不需要你自己去管理。
lorl2 2011-06-21
  • 打赏
  • 举报
回复
线程间同步的问题,去看看事件和信号机怎么用的吧
zailushang_ 2011-06-21
  • 打赏
  • 举报
回复
thread学习中,帮顶
airskys 2011-06-21
  • 打赏
  • 举报
回复
顶一下吧,有没有做过vb控制系统的人来说下自己对于实时控制的经验呢
ghost5216 2011-06-16
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 airskys 的回复:]
vb6还是有点区别的,vb6的线程可能是交给操作系统来管理吧。反正我这里做的测试在vb6下每隔5个ms发出一个脉冲,通过示波器检测是可以的,但是在vb。net下发的脉冲基本上都在30ms以上。只是简单测试,没有其他的东西。

引用 11 楼 ghost5216 的回复:

引用 9 楼 airskys 的回复:
但是我在vb6下就可以。net下有一个问题是我后台的程序如果要刷新界面内容需……
[/Quote]
所有的线程都是操作系统管理的
你看到的稳定的5ms可能是因为你的写的VB6程序是单线程程序。
不过,还是老话,即使单线程也保证不了绝对精确的5ms。因为操作系统不只有你的线程,有很多线程。
你想啊,那么多线程要执行,每个线程分配一点时间片,不会给你的线程特殊照顾的。
airskys 2011-06-16
  • 打赏
  • 举报
回复
vb6还是有点区别的,vb6的线程可能是交给操作系统来管理吧。反正我这里做的测试在vb6下每隔5个ms发出一个脉冲,通过示波器检测是可以的,但是在vb。net下发的脉冲基本上都在30ms以上。只是简单测试,没有其他的东西。
[Quote=引用 11 楼 ghost5216 的回复:]

引用 9 楼 airskys 的回复:
但是我在vb6下就可以。net下有一个问题是我后台的程序如果要刷新界面内容需要用begininvoke,不能在后台线程里面直接设置界面text的值。所以在net下必须要用线程。
而vb6下就可以用,我用时钟起一个while(flag)的方法,这个方法就可以一直不停的运行,时间我也能够控制,5毫秒发送一次数据。但是在vb。net下就不行。如果是操作系统的……
[/Quote]
ghost5216 2011-06-16
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 airskys 的回复:]
但是我在vb6下就可以。net下有一个问题是我后台的程序如果要刷新界面内容需要用begininvoke,不能在后台线程里面直接设置界面text的值。所以在net下必须要用线程。
而vb6下就可以用,我用时钟起一个while(flag)的方法,这个方法就可以一直不停的运行,时间我也能够控制,5毫秒发送一次数据。但是在vb。net下就不行。如果是操作系统的问题,那为啥vb6下的就可以呢。
我觉得还……
[/Quote]
如何刷新界面不是问题
但即使你用VB6也不能精确控制时间
因为系统中不只有你自己的线程,还有其他进程的线程,系统的线程等等。
一旦发生线程调度,你就无法控制时间片。
线程调度和VB6 .NET语言什么的没有关系。
你所谓的好使,只不过是你没有看到明显的异常或者BUG而已。
不代表能精确控制时间。
airskys 2011-06-16
  • 打赏
  • 举报
回复
看我上面的回复,我不认为这个和cpu或者操作系统有关,因为同样的系统,我vb6的程序就跑的很好,但是移植到vb。net下,由于需要线程而造成我时间的控制不准确
[Quote=引用 8 楼 anbam 的回复:]

您需要确认,你的cpu的是否支持小于5ms的线程调用,你的系统中线程调度的时间片是否小于5ms
[/Quote]
airskys 2011-06-16
  • 打赏
  • 举报
回复
但是我在vb6下就可以。net下有一个问题是我后台的程序如果要刷新界面内容需要用begininvoke,不能在后台线程里面直接设置界面text的值。所以在net下必须要用线程。
而vb6下就可以用,我用时钟起一个while(flag)的方法,这个方法就可以一直不停的运行,时间我也能够控制,5毫秒发送一次数据。但是在vb。net下就不行。如果是操作系统的问题,那为啥vb6下的就可以呢。
我觉得还是线程控制的问题,可能我对于这种时间要求精度比较高的线程控制不会,或者有些方法是我不知道的,所以来论坛上请教一下大家。
在net下如何精确的控制线程的运行时间。


[Quote=引用 7 楼 ghost5216 的回复:]

用多线程无法精确控制时间

因为你控制不了线程调度
Sleep之后无法确定什么时候再获得CPU
CPU调度要20ms左右,这个值本身就不固定。
你Sleep(5);只表示你释放CPU5ms,不能保证你5ms之后还拥有CPU,所以发生40ms的事是很正常的。
因为windows不是实时操作系统,是抢占式的。
你可以尝试提高工作线程的优先级,以及应用程序优先级。
即使这样也只是略尽人……
[/Quote]
anbam 2011-06-16
  • 打赏
  • 举报
回复
您需要确认,你的cpu的是否支持小于5ms的线程调用,你的系统中线程调度的时间片是否小于5ms
ghost5216 2011-06-16
  • 打赏
  • 举报
回复
用多线程无法精确控制时间

因为你控制不了线程调度
Sleep之后无法确定什么时候再获得CPU
CPU调度要20ms左右,这个值本身就不固定。
你Sleep(5);只表示你释放CPU5ms,不能保证你5ms之后还拥有CPU,所以发生40ms的事是很正常的。
因为windows不是实时操作系统,是抢占式的。
你可以尝试提高工作线程的优先级,以及应用程序优先级。
即使这样也只是略尽人事。
airskys 2011-06-16
  • 打赏
  • 举报
回复
beginincoke我也用,主要是界面数据刷新的时候用,我设置的是40ms刷新一次,因为人眼的反应也就是这么快了。不过后台线程占用cpu资源的问题没有得到解决,我的线程需要不停的运行,有可能一个毫秒都会运行几次,可能实际我控制时间不能超过5个毫秒,也就是下位机有反应后我上位机在5个毫秒内要做出动作,主要是这5个毫秒控制不了。Thread.sleep(5),有的时候是5个ms有的时候可能就是50个ms

[Quote=引用 3 楼 sp1234 的回复:]

随便搜了一篇文章,我用两三秒钟看了一下,似乎跟你的要求贴近。http://www.360doc.com/content/11/0410/07/2097544_108524961.shtml
[/Quote]
airskys 2011-06-16
  • 打赏
  • 举报
回复
关键你开这两个线程,如何控制其运行时间,精确的控制。
[Quote=引用 2 楼 bdmh 的回复:]

那两个玩意都不要加,后台开一个线程,接收数据,收到数据先放到内存(比如列表)中,然后再有一个线程负责对列表中的数据逐条进行处理
[/Quote]
airskys 2011-06-16
  • 打赏
  • 举报
回复
我这个后台程序确实需要每时每刻来执行的,1ms至少执行一次。因为是实时控制,如果不用的话,这个线程就会一直霸占住系统资源,如何有效的释放呢?
[Quote=引用 1 楼 xuexiaodong2009 的回复:]

我发现如果在后台的线程中不加入Application.doevent,或者Thread.sleep,那么程序就会假死,

代码问题
[/Quote]
airskys 2011-06-16
  • 打赏
  • 举报
回复
我是用这样的方法写的,但是这样的话会造成界面假死,毕竟我的轮询太快了,不到1毫秒while里面的就执行好几遍了。cpu被死死的占着。
[Quote=引用 14 楼 lgqt 的回复:]

你自己写得有问题。
1:你应该先启动一个线程,该线程的代码是While死循环。循环里面每隔一段时间接收数据。
2:你在写一个线程,该线程的代码也是While死循环,该循环里面每隔一段时间显示数据,但是显示数据的时候必须用委托,委托到界面控件线程上来显示数据。
[/Quote]
hwbox 2011-06-16
  • 打赏
  • 举报
回复
标准的生产者-消费者模式啊,你用阻塞队列不就完了,还能确保时序。自己费什么劲做线程调度啊,让信号量去调度。
lgqt 2011-06-16
  • 打赏
  • 举报
回复
你自己写得有问题。
1:你应该先启动一个线程,该线程的代码是While死循环。循环里面每隔一段时间接收数据。
2:你在写一个线程,该线程的代码也是While死循环,该循环里面每隔一段时间显示数据,但是显示数据的时候必须用委托,委托到界面控件线程上来显示数据。
加载更多回复(3)

111,094

社区成员

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

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

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