1

I have a program written in C#, VS 2005. It has a feature of recording data and timestamp. I need millisecond level time resolution because the data sampling cycle time maybe 50ms or less. I used DateTime.Now.Millisecond to retrieve system time, but I found on some computers, the actual intervals between two timestamps are not 50ms but 62-63ms.

So I simplified my code and tried on several computers, here is the code:

static void Main(string[] args)
{
    while (true)
    {
        Thread.Sleep(50);
        Console.WriteLine("{0}", DateTime.Now.Millisecond);
    }
}

Here is the result on Win7 SP1:

928 991 53 116 178 240 306 368 431 493 555 618 ...

Note that the interval is about 62-63ms.

I know that Windows NT series OS time resolution is about 16ms so I'm not very surprised about the result.

BUT, the question is that when I test the same program on some other Win7(SP1) computers, the result is accurate and the intervals are almost always 50ms, I don't know why the behavior differs so much.

So, my question are:

  1. How to explain these results?
  2. How could I get accurate millisecond level timestamp? Is it possible(on Win7)?

BTW,

1) I test it on Win10, the interval is about 50-51ms.

2) I tried using Stopwatch, it has no effect.

3) Environment.TickCount is not accurate too.

4) I tried using VS 2015, the same result.

========================================

here is my new test code:

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

Here is the output result, we can see the second column (DateTime.Now.Millisecond), the interval is exactly 50 msec while the last column(TickCount) varies.

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
Kang Kai
  • 21
  • 1
  • 3
  • 1
    https://blogs.msdn.microsoft.com/ericlippert/2010/04/08/precision-and-accuracy-of-datetime/ – mjwills Jan 15 '19 at 08:33
  • Sleeping threads are eligible to start running again at the clock interrupt. The "heart beat" of the OS, it jerks the processor back alive from the HALT state. The thread scheduler runs to check if any work needs to be done. The default rate is 64 interrupts per second, or 15.625 msec per tick. In other words, you won't get 50 msec but the next integer multiple, 4 * 15.625 = 62.5 msec. You can tinker with this rate, a browser normally does so since it likes a 10 msec service rate to animate images. Should be readily visible with your test. Pinvoke timeBeginPeriod(10). – Hans Passant Jan 15 '19 at 08:41
  • @Hans, I found this kind of result: based on "Sleep(50)", Environment.TickCount increases 47 or 62 msec every time, this proof what you post, but at the same time, DateTime.Now.Millisecond may align to 50 msec, I don't know how to explain it. – Kang Kai Jan 15 '19 at 10:30
  • That is not possible, DateTime.Now gets updated by the exact same interrupt handler. We'd love to see your repro code/results. – Hans Passant Jan 15 '19 at 10:37
  • @Hans, see my updated post please. – Kang Kai Jan 15 '19 at 11:18

1 Answers1

5

DateTime.Now is fed by the system clock, which does not provide the accuracy required for exact performance measurements. For more precise measurements, use Stopwatch, which is fed by the system precision timer, if one is available.

Another problem is that you are assuming that Thread.Sleep will make the current thread sleep for an exact amount of time. This is not the case. The system does not guarantee you that control will return immediately after sleep is over. There might be other threads getting preference and so your thread might resume later than the sleep time.

Sefe
  • 13,731
  • 5
  • 42
  • 55
  • Thank you for the answer, I know that DateTime.Now and Thread.Sleep are both not accurate enough, my question is that why sometimes the result aligns to 50ms and some other times it aligns to 62ms, these two results occurred on Win7, but it always aligns to 51-52ms on Win10. – Kang Kai Jan 15 '19 at 09:28