当前位置:  开发笔记 > 编程语言 > 正文

DateTime.Now多久更新一次?或者是否有更精确的API来获取当前时间?

如何解决《DateTime.Now多久更新一次?或者是否有更精确的API来获取当前时间?》经验,为你挑选了2个好方法。

我有一个循环运行的代码,它根据当前时间保存状态.有时这可能只相差几毫秒,但由于某些原因,似乎DateTime.Now将始终返回至少10 ms的值,即使它仅在2或3 ms之后.这是一个主要问题,因为我保存的状态取决于它保存的时间(例如录制内容)

我的测试代码返回10 ms的每个值:

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);
}

是否有另一种解决方案可以获得精确的当前时间到毫秒?

有人建议看秒表类.虽然秒表类是非常准确的,但它并没有告诉我当前的时间,我需要的东西是为了保存程序的状态.



1> Roman Starko..:

奇怪的是,你的代码在我的Win7下的四核上运行得非常好,几乎每次都产生相距2毫秒的值.

所以我做了一个更全面的测试.这是我的示例输出Thread.Sleep(1).代码打印DateTime.UtcNow循环中连续调用之间的ms数:

睡觉1

每行包含100个字符,因此在"干净运行"中表示100毫秒的时间.所以这个屏幕大约需要2秒钟.最长的抢占时间是4毫秒; 此外,当每次迭代花费1毫秒时,有一个持续约1秒的周期.这几乎是实时操作系统的质量!1 :)

所以我再次尝试,Thread.Sleep(2)这次:

睡觉2

再次,几乎完美的结果.这一次每行的长度为200ms,并且运行时间差不多为3秒,其中间隙从未超过2ms.

当然,接下来要看的是DateTime.UtcNow我机器上的实际分辨率.这是一场完全没有睡觉的跑步; 一个.印,如果UtcNow不改变在所有:

没睡觉

最后,在调查一个奇怪的时间戳相差15ms的情况下,在产生上述结果的同一台机器上,我遇到了以下奇怪的事件:

在此输入图像描述 在此输入图像描述

Windows API中有一个函数被调用timeBeginPeriod,哪些应用程序可以用来暂时增加定时器频率,所以这可能就是这里发生的事情.定时器分辨率的详细文档可通过硬件开发中心存档获得,特别是Timer-Resolution.docx(一个Word文件).

结论:

DateTime.UtcNow 可以有比15ms更高的分辨率

Thread.Sleep(1) 可以睡1ms

在我的机器上,UtcNow增长一次只增加1ms(给出或采取舍入错误 - 反射器显示有一个分区UtcNow).

当所有内容都是基于15.6ms的时候,进程可以切换到低分辨率模式,而高速分辨率模式,有1ms分片,可以在运行中进行切换.

这是代码:

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%,则图像会完全改变,并且在任何地方都会有长时间的抢占.


最后两句话相当重要:-)
存在记录的功能也改变了计时器分辨率.这些方法是[timePeriodBegin](http://msdn.microsoft.com/en-us/library/windows/desktop/dd757624%28v=vs.85%29.aspx)和[timePeriodEnd](http:// msdn. microsoft.com/en-us/library/windows/desktop/dd757626%28v=vs.85%29.aspx)

2> Chris..:

处理毫秒时DateTime的问题不是由于DateTime类,而是与CPU标记和线程切片有关.本质上,当调度程序暂停操作以允许其他线程执行时,它必须在恢复之前至少等待1个时间片,这在现代Windows操作系统上大约需要15ms.因此,任何暂停低于15ms精度的尝试都会导致意外结果.


您认为10毫秒限制来自哪里?提示:这不是任意的.
嗯,问题是因为DateTime.Now的分辨率为10毫秒...请参阅http://msdn.microsoft.com/en-us/library/system.datetime.now.aspx
推荐阅读
echo7111436
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有