简体   繁体   English

为什么Thread.Sleep长时间不精确?

[英]Why is Thread.Sleep is not precise for long durations?

I have a service written in C#. 我有一个用C#编写的服务。 Service is active around the clock but one thread sleeps via Thread.Sleep till a predetermined time - typically 9PM - 11pm - to perform some housekeeping tasks. 服务全天候处于活动状态,但是一个线程通过Thread.Sleep休眠,直到预定时间(通常是晚上9点至晚上11点)才能执行一些内部管理任务。 First time service starts, it calculates time span in mseconds till the housekeeping time and calls Thread.Sleep using that time span. 第一次服务启动时,它将计算直到整理服务时间为止的时间范围(以毫秒为单位),并使用该时间范围调用Thread.Sleep。 Next time the thread simply calls Thread.Sleep(24*60*60*1000) to sleep 24 hours. 下次线程仅调用Thread.Sleep(24 * 60 * 60 * 1000)睡眠24小时。

It works just fine except a single installation when Sleep wakes few minutes earlier - 5-8 minutes earlier according to the trace log. 根据睡眠日志,它可以正常工作,但单次安装可以使 Sleep提前几分钟-早于跟踪日志5-8分钟。 Over several weeks, housekeeping time shifts few hours. 在数周的时间里,客房服务时间会转移几个小时。 I can expect that the housekeeping time can shift forward - not backwards. 我可以预料,客房整理时间可以向前移动-而不能向后移动。 Wondering if anyone can have an explanation. 想知道是否有人可以解释。 I must admit that I am not looking for a different solution to fix the problem - just trying to explain the behavior. 我必须承认,我不是在寻找解决问题的其他解决方案-只是试图解释这种现象。

Thread.Sleep is not designed for long accurate sleeps like you are doing. Thread.Sleep不适用于像您一样长时间的准确睡眠。 You should be using somthing like System.Threading.Timer . 您应该使用诸如System.Threading.Timer之类的东西 You can give it a first run time of midnight, and have it go off every 24 hours. 您可以给它一个午夜的首次运行时间,并使其每24小时关闭一次。 the Timer(TimerCallback, Object, TimeSpan, TimeSpan) constructor is exactly what you are looking for. Timer(TimerCallback, Object, TimeSpan, TimeSpan)构造函数正是您要寻找的。

Sleep doesn't use wall clock for time calculations. 睡眠不使用挂钟进行时间计算。 It uses regular interrupt intervals which come approximately every 10ms (adjustable and OS version dependent) for this. 为此,它使用常规的中断间隔,该间隔大约每10毫秒一次(可调且取决于OS版本)。 The time source which is used for these interrupts is a cheap quartz which was historically was used for some other functions, so its frequency is both not exactly 1/10ms and fluctuates from one machine to another. 用于这些中断的时间源是廉价的石英,该石英过去一直用于其他功能,因此其频率不完全是1 / 10ms,并且会在一台机器之间波动。

The correct approach to solving your problem would be sleeping for much shorter periods of time and checking if the time has come to wake up for real. 解决问题的正确方法是睡眠时间短得多,并检查时间是否真的可以唤醒。

Also, here's hoping that when you say you're using Sleep(), in fact you're waiting for an event with a timeout. 另外,希望当您说正在使用Sleep()时,实际上您正在等待具有超时的事件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM