Windows sleep API is not working

Swanand 101 Reputation points
2023-07-26T08:58:48.15+00:00

I am using Windows Sleep API to wait for 1ms. I understand Windows is not RTOS and it may take ~1.5ms to 2ms on my machine. I have also tested on another machine it behaves same.

On one of our customer, Sleep(1) is taking 15ms or more which is not expected, time delta for 1-2ms is OK but 15ms or more, which is not expected. We don't have any clue why Sleep API is behaving differently on his machine. Can you please help us with direction?

Customer machine configuration :

  • operating system : Windows 10 x64 build 19044
  • system language : Hungarian
  • processors : 12x Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz
  • physical memory : 718/8031 MB (free/total)
  • free disk space : (C:) 37,27 GB
  • display mode : 1920x1080, 32 bit
Windows for business Windows Client for IT Pros User experience Other
Developer technologies C++
{count} votes

Accepted answer
  1. Minxin Yu 13,501 Reputation points Microsoft External Staff
    2023-07-26T09:50:59.6266667+00:00

    Hi,

    You could refer to the similar thread:

    Timers other than Stopwatch are incremented by the clock interrupt. Which by default ticks 64 times per second on Windows. Or 15.625 milliseconds. So a Thread.Sleep() argument less than 16 doesn't give you the delay you are looking for, you'll always get at least that 15.625 interval. Similarly, if you read, say, Environment.TickCount or DateTime.Now and wait less than 16 millisecond then you'll read the same value back and think 0 msec has passed.

    Thread.Sleep Method

    The system clock ticks at a specific rate called the clock resolution. The actual timeout might not be exactly the specified timeout, because the specified timeout will be adjusted to coincide with clock ticks. For more information on clock resolution and the waiting time, see the Sleep function from the Windows system APIs.

    Best regards,

    Minxin Yu


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.
    0 comments No comments

2 additional answers

Sort by: Most helpful
  1. Castorix31 90,521 Reputation points
    2023-07-26T09:34:56.4266667+00:00

    It is explained in the doc :

    This function causes a thread to relinquish the remainder of its time slice and become unrunnable for an interval based on the value of dwMilliseconds. The system clock "ticks" at a constant rate. If dwMilliseconds is less than the resolution of the system clock, the thread may sleep for less than the specified length of time. If dwMilliseconds is greater than one tick but less than two, the wait can be anywhere between one and two ticks, and so on. To increase the accuracy of the sleep interval, call the timeGetDevCaps function to determine the supported minimum timer resolution and the timeBeginPeriod function to set the timer resolution to its minimum. Use caution when calling timeBeginPeriod, as frequent calls can significantly affect the system clock, system power usage, and the scheduler. If you call timeBeginPeriod, call it one time early in the application and be sure to call the timeEndPeriod function at the very end of the application.

    0 comments No comments

  2. Swanand 101 Reputation points
    2023-07-26T14:10:24.0933333+00:00

    Thank you all for your response. I would like to know your suggestion, which solution is better in other words safe to use and consume less resources.

    #1. One solution is to use timeBeginPeriod and timeEndPeriod.

    #2. Other might be use QueryPerformanceCounter and create self HigResTimer sleep function like below, I know this will consume CPU usage, which is inevitable.

    void HighResSleep(double dwMicroSec)
    {
      LARGE_INTEGER StartingTime, EndingTime, ElapsedMicroseconds;
      LARGE_INTEGER Frequency;
      double dwElapse = 0.0;
    
      QueryPerformanceFrequency(&Frequency);
      QueryPerformanceCounter(&StartingTime);
    
      while (dwMicroSec > dwElapse)
      {
        QueryPerformanceCounter(&EndingTime);
        ElapsedMicroseconds.QuadPart = EndingTime.QuadPart - StartingTime.QuadPart;
        dwElapse = double(ElapsedMicroseconds.QuadPart * 1000000.0) / Frequency.QuadPart;
      }
    }
    
    

    #3. Try with C++11 style sleep function, I guess this will give same effect as ::Sleep API. I dont know internals how it differ from Sleep.

    std::this_thread::sleep_for(std::chrono::milliseconds(x));
    

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.