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

问题描述

我有一个循环中运行的代码,它基于当前时间保存状态。有时这可能只是几毫秒,但由于某种原因,似乎DateTime.Now将始终返回至少10 ms的值,即使只有2或3 ms以后。这是一个主要的问题,因为我保存的状态取决于保存的时间(例如记录某些东西)



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

  public static void Main()
{
var dt1 = DateTime.Now;
System.Threading.Thread.Sleep(2);
var dt2 = DateTime.Now;

//在我的机器上,值将至少为10 ms。
Console.WriteLine(First:{0},Second:{1},dt1.Millisecond,dt2。毫秒);
}

有没有另一个解决方案如何获得准确的当前时间,直到毫秒?



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

解决方案>

好奇的是,你的代码在Win7下的四核心上工作得很好,几乎每次都产生了两秒钟的间隔。



所以我做了更多彻底测试。以下是 Thread.Sleep(1)的示例输出。代码在循环中打印连续调用之间的数量为 DateTime.UtcNow





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



所以我再试一次,使用 Thread.Sleep(2 )此次:





再次,几乎完美的结果。这一次,每一行都是200ms长,而且差不多有3秒钟的时间,差距绝对不是2ms。



自然而然,接下来要看的是在我的机器上的 DateTime.UtcNow 的实际分辨率。这是一个没有睡觉的跑步; 。如果 UtcNow 没有更改,则打印





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






Windows API中有一个名为哪些应用程序可以用来临时增加定时器频率,所以这可能是在这里发生了什么。定时器解析的详细文档可通过(一个Word文件)。



结论:




  • DateTime.UtcNow 可以的分辨率高于15ms

  • Thread.Sleep(1) 可以睡眠正好为1ms

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

  • 可以将流程切换到低分辨率模式,当所有内容都以15.6ms为基准时,高速模式即可实现1ms切片。



这是这个e代码:

  static void Main(string [] args)
{
Console.BufferWidth =控制台.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);打破;
case 20000:case 20001:case 20002:Console.ForegroundColor = ConsoleColor.Green; Console.Write(2);打破;
案例30000:案例30001:案例30002:Console.ForegroundColor = ConsoleColor.Yellow; Console.Write(3);打破;
default:Console.Write([{0:0。###}],diff / 10000.0);打破;
}
Console.ForegroundColor = ConsoleColor.Gray;
lastticks + = diff;
}
}

事实证明,存在一个无法更改的功能,定时器分辨率。我没有调查细节,但我以为我会在这里发布一个链接:。




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)

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.

解决方案

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

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:

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! :)

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

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.

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:

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:

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).

Conclusions:

  • 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.

Here's the 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;
    }
}

It turns out there exists an undocumented function which can alter the timer resolution. I haven't investigated the details, but I thought I'd post a link here: NtSetTimerResolution.

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

10-19 22:08