【问题标题】:Resolution of DateTime.Now.Millisecond varies on different computers [duplicate]DateTime.Now.Millisecond 的分辨率在不同的计算机上有所不同[重复]
【发布时间】:2019-01-15 08:30:05
【问题描述】:

我有一个用 C# VS 2005 编写的程序。它具有记录数据和时间戳的功能。我需要毫秒级的时间分辨率,因为数据采样周期时间可能是 50 毫秒或更短。 我使用 DateTime.Now.Millisecond 来检索系统时间,但我发现在某些计算机上,两个时间戳之间的实际间隔不是 50 毫秒,而是 62-63 毫秒。

所以我简化了我的代码并在几台电脑上尝试,这里是代码:

static void Main(string[] args)
{
    while (true)
    {
        Thread.Sleep(50);
        Console.WriteLine("{0}", DateTime.Now.Millisecond);
    }
}

这是 Win7 SP1 上的结果:

928 991 53 116 178 240 306 368 431 493 555 618 ...

注意间隔大约是62-63ms。

我知道 Windows NT 系列操作系统的时间分辨率约为 16 毫秒,所以我对结果并不感到惊讶。

但是,问题是,当我在其他一些 Win7(SP1) 计算机上测试相同的程序时,结果是准确的,并且间隔几乎总是 50 毫秒,我不知道为什么行为差异如此之大。

所以,我的问题是:

  1. 如何解释这些结果?
  2. 如何获得准确的毫秒级时间戳?有可能吗(在Win7上)?

顺便说一句,

1)我在Win10上测试过,间隔大概50-51ms。

2) 我试过用秒表,没有效果。

3) Environment.TickCount 也不准确。

4) 我尝试使用 VS 2015,结果相同。

=========================================

这是我的新测试代码:

static void Main(string[] args)
{
    long ticks = DateTime.Now.Ticks;
    int tEV = Environment.TickCount;
    while (true)
    {
        Thread.Sleep(50);
        Console.WriteLine("{0}, {1}, {2}",
            DateTime.Now.Ticks - ticks,
            DateTime.Now.Millisecond,
            Environment.TickCount - tEV);
        ticks = DateTime.Now.Ticks;
        tEV = Environment.TickCount;
    }
}

这是输出结果,我们可以看到第二列(DateTime.Now.Millisecond),间隔正好是50毫秒,而最后一列(TickCount)变化。

510000, 547, 47
500000, 597, 62
500000, 647, 47
500000, 697, 47
500000, 747, 46
500000, 797, 47
500000, 847, 63
500000, 897, 46
500000, 947, 47
500000, 997, 47
500000, 47, 47
500000, 97, 62
500000, 147, 47
500000, 197, 47
500000, 247, 47
500000, 297, 46
500000, 347, 63
500000, 397, 47
500000, 447, 46
500000, 497, 47
500000, 547, 47
500000, 597, 62
500000, 647, 47
500000, 697, 47
500000, 747, 47
500000, 797, 62
500000, 847, 47
500000, 897, 47
500000, 947, 47
500000, 997, 46
500000, 47, 63

【问题讨论】:

  • 休眠线程有资格在时钟中断时再次开始运行。操作系统的“心跳”,它将处理器从 HALT 状态猛拉回来。线程调度程序运行以检查是否需要完成任何工作。默认速率为每秒 64 次中断,或每滴答声 15.625 毫秒。换句话说,你不会得到 50 毫秒,而是下一个整数倍,4 * 15.625 = 62.5 毫秒。您可以修改这个速率,浏览器通常会这样做,因为它喜欢 10 毫秒的服务速率来为图像设置动画。在您的测试中应该很容易看到。调用 timeBeginPeriod(10).
  • @Hans,我发现了这种结果:基于“Sleep(50)”,Environment.TickCount 每次增加 47 或 62 毫秒,这证明了您发布的内容,但同时, DateTime.Now.Millisecond 可能对齐到 50 毫秒,我不知道如何解释。
  • 这是不可能的,DateTime.Now 由完全相同的中断处理程序更新。我们很乐意看到您的重现代码/结果。
  • @Hans,请看我更新的帖子。

标签: c#


【解决方案1】:

DateTime.Now 由系统时钟提供,不能提供精确性能测量所需的精度。如需更精确的测量,请使用Stopwatch,它由系统精度计时器提供(如果有)。

另一个问题是您假设Thread.Sleep 将使当前线程休眠一段确切的时间。不是这种情况。系统不保证您在睡眠结束后立即恢复控制。可能有其他线程获得偏好,因此您的线程可能会在睡眠时间之后恢复。

【讨论】:

  • 谢谢你的回答,我知道 DateTime.Now 和 Thread.Sleep 都不够准确,我的问题是为什么有时结果对齐到 50ms 而其他时候对齐到 62ms,这两个结果出现在 Win7 上,但在 Win10 上总是对齐到 51-52ms。
猜你喜欢
  • 1970-01-01
  • 2023-02-23
  • 2017-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多