2

The Window's default precision for Thread.Sleep() is 15.625 ms (1000 / 64), i.e. if you call Thread.Sleep(1), the time elapsed is 15 ms or 16 ms. I want to improve the accuracy to 1 ms.

There's a function "timeBeginPeriod" which can change the accuracy. But I didn't get what I want. Here's my code:

[DllImport("winmm.dll", EntryPoint = "timeBeginPeriod")]
public static extern void TimeBeginPeriod(int t);

[DllImport("winmm.dll", EntryPoint = "timeEndPeriod")]
public static extern void TimeEndPeriod(int t);

TimeBeginPeriod(1);
var t1 = Environment.TickCount;
Thread.Sleep(1);
var t2 = Environment.TickCount;
Console.WriteLn(t2 - t1);
TimeEndPeriod(1);

What I expected is 1 or 2, but I got 15 or 16 actually.

Is there any code I missed?

Qingxin Xu
  • 23
  • 7
  • Did you try the same *without* `Thread.Sleep`? I'd be curious as to what the difference would be between `t1` and `t2` – Rafalon Apr 10 '19 at 11:05
  • From `Thread.Sleep` documentation: **The actual timeout might not be exactly the specified timeout, because the specified timeout will be adjusted to coincide with clock ticks** – Alessandro D'Andria Apr 10 '19 at 11:07
  • you never will get get the expected 1 or 2ms, because with the time to do a Thread.Sleep is minimum 4 or 5ms – Frenchy Apr 10 '19 at 11:10
  • I don't know how often `Environment.TickCount` gets updated and if that is indeed affected by setting the timer resolution, but calling `TimeBeginPeriod(1)` does indeed change the resolution of `Sleep()` to (about) 1 millisecond for me. – 500 - Internal Server Error Apr 10 '19 at 11:17
  • 1
    From my personal experience, `Thread.Sleep` is totally unreliable even setting `TimeBeginPeriod`. Better to use [Multimedia Timers](https://learn.microsoft.com/en-us/windows/desktop/multimedia/about-multimedia-timers). – Alessandro D'Andria Apr 10 '19 at 11:27

2 Answers2

0

Based on discussions in various forums, I have the suspicion that this feature was broken on Windows 10 for a while, but it appears to be fixed on my machine running Windows 10 version 2004. Without the call to timeBeginPeriod, the sleep timer has a resolution of ~15ms. After calling timeBeginPeriod(1), the sleep timer resolution goes down to 1..2 ms

Can others confirm this on an up-to-date Windows system?

Addendum 1: I just found https://stackoverflow.com/a/48011619/295690 which indicates that even though the feature might actually be repaired, there are good reasons to avoid it anyway.

Addendum 2: Even more insight from https://randomascii.wordpress.com/2013/07/08/windows-timer-resolution-megawatts-wasted/ leads me to assume that it is not just a matter of the OS version. I could well imagine that certain power saving modes or hardware configurations prevent programs from increasing the system-wide tick frequency.

0

I have some update about this problem.

The accuracy of Environment.TickCount is about 16ms.It's not a high precision method. Actually by using DateTime, we can get more accurate elapse time even without using TimeBeginPeriod/TimeEndPeriod on Windows 10, Version 1903.

long t1 = Environment.TickCount;
DateTime dt1 = DateTime.Now;
Thread.Sleep(1);
DateTime dt2 = DateTime.Now;
long t2 = Environment.TickCount;
Console.WriteLine("DateTime Method: " + (dt2-dt1).TotalMilliseconds);
Console.WriteLine("TickCount Method: " + (t2 - t1));

DateTime Method: 2.0074
TickCount Method: 0
Qingxin Xu
  • 23
  • 7