获得 2 毫秒是相当不寻常的,大多数运行您的代码的人都会获得 15 毫秒。它相当依赖于机器,并且主要取决于您在机器上运行的其他程序。例如,更改它的一种方法是启动 Chrome,您会看到(接近)1 毫秒的睡眠时间。
您应该显示更多数字以避免舍入伪影。代码简化:
static void Main(string[] args) {
Stopwatch st = new Stopwatch();
while (true) {
st.Restart();
System.Threading.Thread.Sleep(1);
st.Stop();
Console.Write("{0} ", st.Elapsed.Ticks / 10000.0);
System.Threading.Thread.Sleep(200);
}
}
在我的机器上产生:
16.2074 15.6224 15.6291 15.5313 15.6242 15.6176 15.6152 15.6279 15.6194 15.6128
15.6236 15.6236 15.6134 15.6158 15.6085 15.6261 15.6297 15.6128 15.6261 15.6218
15.6176 15.6055 15.6218 15.6224 15.6212 15.6134 15.6128 15.5928 15.6375 15.6279
15.6146 15.6254 15.6248 15.6091 15.6188 15.4679 15.6019 15.6212 15.6164 15.614
15.7504 15.6085 15.55 15.6248 15.6152 15.6248 15.6242 15.6158 15.6188 15.6206 ...
这是正常输出,我的机器上没有运行任何与操作系统混淆的程序。这将是它在大多数机器上的工作方式。
关于正在发生的事情的一些背景。当您使用大于 0 的值调用 Thread.Sleep() 时,您会自愿放弃处理器并且您的线程进入等待状态。当操作系统的线程调度程序运行并且足够的时间到期时,它将恢复。
这句话的关键是“线程调度程序运行时”。它在 Windows 中的不同时间运行,由将处理器从 HALT 状态唤醒的时钟中断驱动。这从内核开始,时钟中断的一项主要任务是增加时钟值。例如,DateTime.Now 和 Environment.TickCount 使用的那个
时钟没有无限分辨率,只有在时钟中断发生时才会改变。默认情况下,在所有现代 Windows 版本上,时钟中断每秒发生 64 次。这使得时钟精度为 1 / 64 = 15.625 毫秒。您可以在我机器上的程序输出中清楚地看到这个值。
所以你的机器上发生的事情是一个程序改变了时钟中断率。这是从第一个支持多媒体计时器的 Windows 版本 Windows 3.1 的一个相当不幸的继承。可以高速滴答的计时器以支持需要处理媒体的程序,例如动画 GIF 文件、调整视频播放器的帧速率、保持声卡没有卡顿或过度延迟的情况下提供声音。 Chrome 等程序。
他们通过调用timeBeginPeriod() 来完成此操作。他们通常会全力以赴并选择最小的允许值,即 1 毫秒。您的机器上显然是 2 毫秒。您也可以这样做,您会看到 Sleep(1) 调用现在需要大约 1 毫秒而不是 2 毫秒。当您不再需要高速率时,不要忘记调用 timeEndPeriod()。
但请记住,这是非常不友好的事情。唤醒处理器这通常对电池寿命非常不利,这在便携式机器上总是一个问题。这解释了该网站的创始人在他的博客文章"Why does Windows have terrible battery life" 中所迷惑的原因。不是,Chrome 的电池寿命很差 :) 如果你想找出是什么程序弄乱了时钟,那么你可以从命令行运行 powercfg -energy。