Thread.Sleep的精度还差吗?

Is the precision of Thread.Sleep still poor?

我的印象是 Thread.Sleep(x) 并不精确,它所做的只是让线程在 最小值 x 毫秒内休眠。参见 here, here and here

当睡眠时间很短时,例如1ms,预计您会发现线程偶尔会休眠约 15ms。这是 apparently,因为时钟中断率默认为每秒 64 次。

几年前我试过这个,事实上,我也体验过 15ms 分辨率。但是,我刚刚再次尝试,现在我看到 1ms2ms 的分辨率很少超过 2 毫秒。

发生了什么变化? .NET 是否发生了变化(我现在正在使用 4.6,不记得我 2 年前使用的是什么)?也许是操作系统发生了变化? (我曾经并且仍在使用 AWS EC2 Windows 服务器,但也许有更新。)

我的简单测试程序:

private static Stopwatch sw =new Stopwatch();
static void Main(string[] args)
{
    var timer = new Stopwatch();
    var results = new List<long>();
    for (int i = 0; i < 100000; i++)
    {
        timer.Restart();
        Thread.Sleep(1);
        results.Add(timer.ElapsedMilliseconds);
    }

    foreach (var item in results.Where(x => x > 1).ToList())
    {
        Console.WriteLine(item );
    }

    Console.ReadLine();

}

Thread.Sleep(以及kernel32中的底层WindowsAPISleep函数)的精度取决于系统时钟的分辨率, 的默认滴答速率约为 15 毫秒 。应用程序可以请求更高的分辨率,在这种情况下,全局使用请求的最高分辨率

在这种情况下,您可能会看到低于 15 毫秒的分辨率,因为您系统上的某些东西 运行 请求了更高的分辨率。

如果您的应用程序确实需要低于 15 毫秒的睡眠时间,它可以通过本机 timeBeginPeriod 函数请求更高的分辨率。

但是,请注意,底层计时器设备可能不支持您请求的分辨率,因此编写依赖于此行为的代码不是好的做法,除非您完全确定您的代码将使用的硬件在 运行 上。