问题描述
privatevoidDelay(intt){System.Diagnostics.Stopwatchsw=newSystem.Diagnostics.Stopwatch();sw.Restart();while(sw.ElapsedMilliseconds<t){Thread.Sleep(1);Application.DoEvents();}sw.Stop();}
就很简单的延时程序,但多个地方多线程都用到它,是否会冲突??
解决方案
本帖最后由 sosoben 于 2016-01-22 17:01:34 编辑
解决方案二:
你方法内部都是私有的,不会有冲突,但你每一毫秒就Application.DoEvents(),这个会出问题的
解决方案三:
多线程中私有变量,是没有影响的!
解决方案四:
多线程调用不排队,“时序会乱”搞不懂你什么意思,你使用的都是局部变量没什么不安全。我唯一不理解的是明明一句Thread.Sleep就能解决的事情为何要做的如何麻烦。
解决方案五:
sw.Restart();是不是应该放在DoEvents()后面才有用,那样就类似定时器了如果是那样,System.Threading.Timer可能更适合你也可以借助生产者-消费者模式采用一个定时器,轮询处理所有的延时任务
解决方案六:
正确的事情总是很简单很干净的,而诡异的事情总是就扯在一起的显得很庞大很脏乱。这里至少有3个错误的概念组合在一起:1.既然是子线程,就不用扯什么Application.DoEvents。那个是用在vb5、vb6那样的单线程程序中的语法,在.net中就算是你想写它,也是用在UI主线程上。怎么可能跟“多线程”搅和在一起呢?既然你都多线程了,还在子线程中写什么DoEvents干嘛呢?2.在你的思维中,线程就是要刻意地去“停”那么一段时间,而不是注册一个定时器事件在一定时间唤醒后续的事情。在你看来,一堆什么正事儿也不干的子线程在进程中,对内存使用和CPU使用状况都似乎没有危害似地。3.在你看来,死等的时候,还必须无限制地(理论上顶多隔上1~10毫秒)干一些职责以外的事情,并且具体干什么也不确定,这样才能体现编程比较花哨。
解决方案七:
引用1楼starfd的回复:
你方法内部都是私有的,不会有冲突,但你每一毫秒就Application.DoEvents(),这个会出问题的
引用5楼sp1234的回复:
正确的事情总是很简单很干净的,而诡异的事情总是就扯在一起的显得很庞大很脏乱。这里至少有3个错误的概念组合在一起:1.既然是子线程,就不用扯什么Application.DoEvents。那个是用在vb5、vb6那样的单线程程序中的语法,在.net中就算是你想写它,也是用在UI主线程上。怎么可能跟“多线程”搅和在一起呢?既然你都多线程了,还在子线程中写什么DoEvents干嘛呢?2.在你的思维中,线程就是要刻意地去“停”那么一段时间,而不是注册一个定时器事件在一定时间唤醒后续的事情。在你看来,一堆什么正事儿也不干的子线程在进程中,对内存使用和CPU使用状况都似乎没有危害似地。3.在你看来,死等的时候,还必须无限制地(理论上顶多隔上1~10毫秒)干一些职责以外的事情,并且具体干什么也不确定,这样才能体现编程比较花哨。
谢谢各位大大的指教,我也知道sleep跟doevents用的不对的了。但由于主窗体UI线程也调用过这个delay,这时就需要doevent了。而又不想占用太多CPU处理时间,所以就sleep(1)了。(其实这也是我编程不到家的体现,因为有时候我调试时想分步执行,用多线程就会显得不确定了,于是我就先取消多线程,用窗口线程执行,分步看效果)当然,这都是我的历史遗留问题,按各位的意思,我在主窗体的线程中用doevents,多线程中用sleep就没错了是吗?还有,版主大人,每毫秒就执行一次doevents会出现什么问题?可以说说吗?
解决方案八:
再补充一下,其实是用这个做机械设备的运动控制的在发命令让一个东西动到它的真正到位反馈给我是需要一定时间的延时(到什么位我只能知道个大概,不确定,然后用机器视觉捕捉),所以我就相应延时这样一段时间。这些都在一个子线程里,然后我想急停的话就终止这个线程并停止电机。“注册一个定时器事件在一定时间唤醒后续”这个我不太能理解,有没有相关例程?就是到了需要停的地方不断问某个变量?时间一使它改变了就继续下去?还是说用waithandle?Monitor?
解决方案九:
好像是不更新ui,不知道有没有记错,你可以实验下
解决方案十:
publicvoidUpandDown(doubleoffset1,doubleoffset2,doubleoffset3){System.Threading.ThreadUpDown1=newSystem.Threading.Thread(()=>UpDown(offset1,offset2,offset3));UpDown1.IsBackground=true;UpDown1.Start();Delay(1500);//我怀疑有问题就是这个deley了,当然也有可能是上面的问题//UpDown(offset1,offset2,offset3);}
引用8楼starfd的回复:
好像是不更新ui,不知道有没有记错,你可以实验下
试验结果:如果是主窗口线程(UI)调用,则不加doevents会不更新UI在多线程里用,则加不加都一样(不考虑其他特殊情况),UI都能刷新
解决方案十一:
引用5楼sp1234的回复:
正确的事情总是很简单很干净的,而诡异的事情总是就扯在一起的显得很庞大很脏乱。这里至少有3个错误的概念组合在一起:1.既然是子线程,就不用扯什么Application.DoEvents。那个是用在vb5、vb6那样的单线程程序中的语法,在.net中就算是你想写它,也是用在UI主线程上。怎么可能跟“多线程”搅和在一起呢?既然你都多线程了,还在子线程中写什么DoEvents干嘛呢?2.在你的思维中,线程就是要刻意地去“停”那么一段时间,而不是注册一个定时器事件在一定时间唤醒后续的事情。在你看来,一堆什么正事儿也不干的子线程在进程中,对内存使用和CPU使用状况都似乎没有危害似地。3.在你看来,死等的时候,还必须无限制地(理论上顶多隔上1~10毫秒)干一些职责以外的事情,并且具体干什么也不确定,这样才能体现编程比较花哨。
还有一种情况是下位机需要一个上升沿信号,而且维持时间要超过100毫秒,这种情况很多,如果都用sleep的话界面也会一卡一卡的。这种情况能应用“注册一个定时器事件在一定时间唤醒后续的事情”吗?大概是个什么样的架构,可以详细介绍下吗?