我有一个关于 C# 线程的小问题。
出于某种原因,当我打开 Chrome 时,我的线程从 32 毫秒延迟加速到 16 毫秒延迟,当我关闭 Chrome 时,它又回到 32 毫秒。我正在使用 Thread.Sleep(1000/60)
来延迟。
有人可以解释为什么会发生这种情况,并可能提出一个可能的解决方案吗?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ConsoleApplication2
{
class Program
{
static bool alive;
static Thread thread;
static DateTime last;
static void Main(string[] args)
{
alive = true;
thread = new Thread(new ThreadStart(Loop));
thread.Start();
Console.ReadKey();
}
static void Loop()
{
last = DateTime.Now;
while (alive)
{
DateTime current = DateTime.Now;
TimeSpan span = current - last;
last = current;
Console.WriteLine("{0}ms", span.Milliseconds);
Thread.Sleep(1000 / 60);
}
}
}
}
最佳答案
只是一个帖子来确认马修的正确答案。 Thread.Sleep() 的准确性受 Windows 时钟中断率的影响。默认情况下,它每秒滴答 64 次,每 15.625 毫秒一次。 Sleep() 只有在发生此类中断时才能完成。这里的心理形象是由“ sleep ”一词引起的,处理器实际上处于 sleep 状态并且不执行代码。只有那个时钟中断会再次唤醒它以恢复执行您的代码。
您选择的 1000/60 是一个非常不愉快的选择,它要求 16 毫秒。略高于 15.625,因此您总是会在至少 2 个滴答后醒来:2 x 15.625 = 31 毫秒。您测量的内容。
但是中断率不是固定的,它可以通过程序改变。它通过调用 CreateTimerQueueTimer() 或遗留的 timeBeginPeriod() 来实现。浏览器通常需要这样做。像动画 GIF 这样简单的事情需要更好的计时器,因为 GIF 帧时间以 10 毫秒为单位指定。或者一般来说,任何与多媒体相关的操作都需要它。
执行此操作的程序的一个非常丑陋的副作用是,这种增加的时钟中断率会产生系统范围的影响。就像它在你的程序中所做的那样。你的计时器突然变得准确了,你实际上得到了你要求的 sleep 时间,16 毫秒。因此 Chrome 正在将速率更改为每秒 1000 次滴答。最大支持。和 good for business当您有竞争操作系统时。
您可以通过选择与默认中断率更接近的 sleep 持续时间来避免此问题。如果您要求 15,那么您将得到 15.625,而 Chrome 无法对此产生影响。 31 是下一个甜蜜点。等等,15.625的整数倍并向下舍入。
更新:请注意此行为已更改 just recently .从 Win10 2004 版本开始,效果不再是全局的,因此 Chrome 无法再影响你的程序。 从 Win11 开始,具有非事件窗口的应用以默认中断率运行。
关于c# - 为什么 Thread.Sleep 在其他应用程序运行时等待的时间比请求的时间长?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19415153/