DateTime.Now更新频率如何? 或者是否有更精确的API来获取
我的代码运行在一个循环中,并且基于当前时间保存状态。 有时候这可能只是几毫秒,但由于某些原因,即使仅仅2或3毫秒后,DateTime.Now总会返回至少10毫秒的值。 这是一个主要问题,因为我保存的状态取决于保存的时间(例如记录某些内容)
我的测试代码每10毫秒返回一个值:
public static void Main()
{
var dt1 = DateTime.Now;
System.Threading.Thread.Sleep(2);
var dt2 = DateTime.Now;
// On my machine the values will be at least 10 ms apart
Console.WriteLine("First: {0}, Second: {1}", dt1.Millisecond, dt2.Millisecond);
}
如何获得准确的当前时间达到毫秒还有另一种解决方案吗?
有人建议看看秒表班。 尽管秒表类非常准确,但它并不告诉我当前时间,这是我需要的,以便保存我的程序状态。
奇怪的是,你的代码在我的Win7下的四核上工作得非常好,几乎每次都会产生相距2毫秒的值。
所以我做了一个更彻底的测试。 这是我的Thread.Sleep(1)
示例输出。 该代码打印循环中对DateTime.UtcNow
连续调用之间的毫秒数:
每行包含100个字符,因此在“全面运行”中表示100毫秒的时间。 所以这个屏幕大约需要2秒。 最长抢占为4ms; 此外,当每次迭代精确到1毫秒时,持续约1秒。 这几乎是实时的操作系统质量!1 :)
所以我这次再次尝试Thread.Sleep(2)
:
再次,几乎完美的结果。 这一次每一行都是200ms长,并且有一个长达3秒的跑步,其间的差距永远不会超过2毫秒。
自然,接下来要看到的是我的机器上的DateTime.UtcNow
的实际分辨率。 这是一场没有睡觉的跑步; a .
如果UtcNow
完全没有改变,则打印出来:
最后,在调查产生上述结果的同一台机器上,间隔15ms的奇怪情况时,我遇到了以下奇怪的事件:
在Windows API中有一个名为timeBeginPeriod
的函数,应用程序可以使用该函数临时增加计时器频率,所以这可能是这里发生的事情。 定时器分辨率的详细文档可通过硬件开发中心档案,特别是Timer-Resolution.docx(一个Word文件)获得。
结论:
DateTime.UtcNow
可以具有比15ms高得多的分辨率 Thread.Sleep(1)
可以睡1ms UtcNow
增长1毫秒(给出或取舍舍错误 - 反射器显示UtcNow
中存在分裂)。 代码如下:
static void Main(string[] args)
{
Console.BufferWidth = Console.WindowWidth = 100;
Console.WindowHeight = 20;
long lastticks = 0;
while (true)
{
long diff = DateTime.UtcNow.Ticks - lastticks;
if (diff == 0)
Console.Write(".");
else
switch (diff)
{
case 10000: case 10001: case 10002: Console.ForegroundColor=ConsoleColor.Red; Console.Write("1"); break;
case 20000: case 20001: case 20002: Console.ForegroundColor=ConsoleColor.Green; Console.Write("2"); break;
case 30000: case 30001: case 30002: Console.ForegroundColor=ConsoleColor.Yellow; Console.Write("3"); break;
default: Console.Write("[{0:0.###}]", diff / 10000.0); break;
}
Console.ForegroundColor = ConsoleColor.Gray;
lastticks += diff;
}
}
事实证明,存在可以改变定时器分辨率的未公开的功能。 我没有调查细节,但我想我会在这里发布一个链接: NtSetTimerResolution
。
1当然,我更加确定操作系统是尽可能空闲的,并且有四个相当强大的CPU核心可供使用。 如果我将所有四个核心加载到100%,则图片完全变化,并且随处都有抢先占用。
DateTime在处理毫秒时的问题根本不是由于DateTime类造成的,而是与CPU ticks和线程片有关。 本质上,当调度程序暂停某个操作以允许其他线程执行时,它必须至少等待一个时间片,然后才能在现代Windows操作系统上恢复大约15ms。 因此,任何暂停时间小于15ms精度的尝试都会导致意想不到的结果。
如果您在做任何事情之前拍摄当前时间的快照,您可以将秒表添加到您存储的时间,不是?
链接地址: http://www.djcxy.com/p/52807.html上一篇: How frequent is DateTime.Now updated ? or is there a more precise API to get the current time?