2011-11-23 67 views
2

我有一个Winform,需要等待大约3-4个小时。我无法关闭并以某种方式重新打开该应用程序,因为它在后台执行某些操作,而它正在等待。Thread.Sleep()睡得更久

为了实现等待 - 不会对UI线程和其他原因造成麻烦 - ,我有一个BackgroundWorker,我可以发送多少毫秒来等待并在其doWork事件中调用Thread.Sleep(waitTime);。在backGroundWorker_RunWorkerCompleted事件中,我会在等待后执行程序应该执行的操作。

这在开发机器上正常工作。即当等待结束时等待结束。但是在测试机器上,它会一直等待更长的时间。它发生两次,第一次等待超过特定时间1小时,第二次等待大约2小时40分钟。

难道这有什么明显的原因发生,或者我错过了什么?

的开发机是Win XP的试机是赢7

+1

为什么不使用Timer控件而不是后台工作器中的thread.sleep? –

+1

同意..计时器应该这样做 –

+1

为什么计时器的准确度比睡眠更好? AFAIK,定时器间隔由线程必须等待的Windows消息队列上的定时等待实现,因此与sleep()相同。使用定时器会让调用线程必须运行消息队列 - 通常这是不可取的。尝试在没有使用sleep()的情况下等待一个通信栈内一小时的深度 - 需要痛苦且容易出错的状态机。 –

回答

2

看一看this article这解释的原因:

Thread.sleep代码(n)表示阻塞当前线程用于至少可Ñ 内发生的数目的时间片(或线程量程)的 毫秒。时间片的长度在Windows和不同处理器的不同 版本/类型上不同,通常 的范围从15到30毫秒不等。这意味着该线程几乎可以保证在012毫秒以上的时间内阻塞超过n个毫秒。您的线程会在n毫秒后重新唤醒的可能性大约为 ,因为这是不可能的。因此,Thread.Sleep对于 时间没有意义。

通过它也解释了为什么不使用的Thread.Sleep的方式;)

我同意其他建议使用定时器,而不是Thread.sleep代码的。

+3

您的引用解释了为什么使用Thread.Sleep进行准确计时并不是一个好主意,但在我看来,它并不能解释为什么Thread.Sleep等待5个小时而不是4个小时。 –

+0

感谢您的链接.. – ViV

+1

@Werner Henze:我认为它可以解释它。由于Thread.Sleep根据您的机器使用了多个时间片,这些时间片都不是确切的,所以差异的总和可能会导致问题。当与机器上运行的其他线程共享时间片时,特别会导致超过一小时的差异。 – MatthiasG

2

在我的愚见,在等待时间上的差异不能仅仅被你给我们的信息解释。我真的认为,差异的原因在于开始睡眠的时刻。所以实际拨打Thread.sleep(waitTime);。你确定在你认为这是睡觉的时刻?

而且,正如评论所建议的,如果你真的需要等待这么久,考虑使用Timer来启动所需的事件。甚至在您的应用程序中安排某种排序。当然,这取决于你的实际执行情况,因此说起来容易做起来难。但是'感觉'很傻,让BackgroundWorker睡了这么久。

+0

我确信睡眠在我认为是的时候被调用。但看到有关Thread.Sleep()的答案和链接,我正在考虑使用Timer,以达到我的目的。 – ViV

3

我建议使用的ManualResetEvent来代替:

http://msdn.microsoft.com/en-us/library/system.threading.manualresetevent.aspx

ManualResetEvent mre = new ManualResetEvent(false); 
mre.WaitOne(waitTime); 

... 
//your background worker process 
mre.Set(); 

作为奖励,你将不得不中断这种睡眠更快的能力。

+0

谢谢!会给它一个镜头。 – ViV

+0

再次,工作在相同的机制睡眠()。同样的问题。定时器是相同的 - 由操作系统在Windows Message Queue超时等待时启动。所有这些定时器/睡眠/等待都使用相同的操作系统功能。 5个小时而不是4个小时只是..很奇怪。 –

0

PREFIX:这就需要。NET 4或更新

考虑让你的异步功能和简单地做:

await Task.Delay(waitTime); 

或者,如果你不能让你的函数异步(或不愿意),你也可以这样做:

Task.Delay(waitTime).Wait(); 

这是一个单线解决方案,任何具有Reflector副本的人都可以验证Task.Delay是否在内部使用计时器。