【发布时间】: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 毫秒,我不知道为什么行为差异如此之大。
所以,我的问题是:
- 如何解释这些结果?
- 如何获得准确的毫秒级时间戳?有可能吗(在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#