本文介绍了如何频繁的是DateTime.Now更新?还是有更多的precise API来获取当前时间?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个循环code运行,它是基于当前时间的节能状态。有时候,这可能是几毫秒分开,但由于某些原因似乎DateTime.Now总是返回至少10毫秒的间隔值,即使它的只有2或3毫秒后。这presents的一大问题,因为国家,我已把取决于它保存的时间(如记录的东西)

I have code running in a loop and it's saving state based on the current time. Sometimes this can be just milliseconds apart, but for some reason it seems that DateTime.Now will always return values of at least 10 ms apart even if it's only 2 or 3 ms later. This presents a major problem since the state i'm saving depends on the time it was saved (e.g. recording something)

我的测试code,返回每个值10毫秒间隔:

My test code that returns each value 10 ms apart:

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

有没有关于如何获得准确的当前时间到毫秒另一种解决方案?

Is there another solution on how to get the accurate current time up to the millisecond ?

有人建议看秒表类。虽然秒表类是非常准确的它并没有告诉我当前的时间,这是我需要为了节省我的程序的状态。

Someone suggested to look at the Stopwatch class. Although the Stopwatch class is very accurate it does not tell me the current time, something i need in order to save the state of my program.

推荐答案

奇怪的是,您code工作完全正常在Win7的在我的四核,产生价值正是2毫秒的间隔几乎每一次。

Curiously, your code works perfectly fine on my quad core under Win7, generating values exactly 2 ms apart almost every time.

所以,我已经做了更详尽的测试。下面是我的示例输出的Thread.Sleep(1)。在code打印的连续调用之间毫秒数 DateTime.UtcNow 在一个循环:

So I've done a more thorough test. Here's my example output for Thread.Sleep(1). The code prints the number of ms between consecutive calls to DateTime.UtcNow in a loop:

每个行包含100个字符,并且时间从而重新presents 100ms的上一个干净运行。因此,该屏幕占地约2秒。最长preemption是4ms的;此外,有一段持续1秒左右时,每一次迭代究竟花了1毫秒。这几乎是实时操作系统质量:!)

Each row contains 100 characters, and thus represents 100ms of time on a "clean run". So this screen covers roughly 2 seconds. The longest preemption was 4ms; moreover, there was a period lasting around 1 second when every iteration took exactly 1 ms. That's almost real-time OS quality! :)

于是我又试了一次,用 Thread.sleep代码(2)这个时候:

So I tried again, with Thread.Sleep(2) this time:

此外,近乎完美的效果。这一次,每一行是200毫秒长,并有一个运行近3秒长的差距在哪里从来没有任何东西比其他完全2ms的。

Again, almost perfect results. This time each row is 200ms long, and there's a run almost 3 seconds long where the gap was never anything other than exactly 2ms.

当然,接下来的事情看到的是 DateTime.UtcNow 我的机器上的实际分辨率。这里有一个没有睡在所有运行; 。一个 打印,如果 UtcNow 并没有改变的所有的:

Naturally, the next thing to see is the actual resolution of DateTime.UtcNow on my machine. Here's a run with no sleeping at all; a . is printed if UtcNow didn't change at all:

最后,在调查一个奇怪的情况下,时间戳是15ms的除了所产生上述结果的同一台机器上,我碰到下面的好奇事件:

Finally, while investigating a strange case of timestamps being 15ms apart on the same machine that produced the above results, I've run into the following curious occurrences:

还有就是Windows API中的函数叫做<$c$c>timeBeginPeriod,该应用程序可以使用临时增加定时器的频率,所以这是presumably这里发生了什么。计时器分辨率的详细文档,可访问硬件开发中心存档,特别是Timer-Resolution.docx (Word文件)。

There is a function in the Windows API called timeBeginPeriod, which applications can use to temporarily increase the timer frequency, so this is presumably what happened here. Detailed documentation of the timer resolution is available via the Hardware Dev Center Archive, specifically Timer-Resolution.docx (a Word file).

结论:

  • DateTime.UtcNow 有一个更高的分辨率比15毫秒
  • 的Thread.Sleep(1) 睡了整整1毫秒
  • 在我的机器上, UtcNow 的增长正好1毫秒的时间(允许有舍入误差成长 - 反射显示,有一个在分工UtcNow )。
  • 这是可能的过程中切换到低分辨率模式下,当一切都15.6ms为主,而高清晰度模式,以1ms的切片,上飞。
  • DateTime.UtcNow can have a much higher resolution than 15ms
  • Thread.Sleep(1) can sleep for exactly 1ms
  • On my machine, UtcNow grows grow by exactly 1ms at a time (give or take a rounding error - Reflector shows that there's a division in UtcNow).
  • It is possible for the process to switch into a low-res mode, when everything is 15.6ms-based, and a high-res mode, with 1ms slices, on the fly.

这里的code:

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

原来存在一个未公开的函数,可以改变定时器的分辨率。我没有调查的细节,但我想我会在这里发布一个链接:<$c$c>NtSetTimerResolution.

当然,我做了额外肯定的是,OS是空闲的时候,也有其掌握4相当强大的CPU内核。如果我加载所有四个核心,以100%的画面完全改变,长preemptions无处不在。

这篇关于如何频繁的是DateTime.Now更新?还是有更多的precise API来获取当前时间?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-23 04:39