Polling by sleeping versus polling by waiting with a timeout

Commenter Francois Boucher asks it's better to write a background worker thread that polls with Sleep() and a flag, or polls by waiting for an event with a timeout?

// method A
while (fKeepGoing) {
 .. a little work ..

// method B
do {
 .. a little work ..
} while (WaitForSingleObject(hEvent, 50) == WAIT_TIMEOUT);

"Which scenario is better? The first one uses only 1 handle for the thread. The second one will use 2. But is the first scenario wasting more thread time? Is it worth using the event (kernel object)?"

Yeah, whatever.

I don't quite understand why you want to pause every so often. Why not just do the work at low priority? When there are more important things to do, your background thread will stop doing whatever it's doing. When there is an available CPU, then your background thread will do its thing as fast as it can (until something with higher priority arrives).

The only thing I can think of is that by adding the pauses, your program won't look like it's consuming 100% CPU while the background processing is going on. Which is true, but then again, that's not much consolation. "Wow, with these changes, my spell check takes only 10% of the CPU. But then again, it also takes 10 times as long." Is that an improvement? You made your customer wait ten times as long for the document to be spell checked. That's ten times less battery life for your laptop.

And generally speaking, polling should be avoided because it carries negative consequences for system performance. So we're basically asking, "Which is better, hammering with a screwdriver or hammering with pliers?"

But let's say for the sake of argument that this "back off periodically" polling loop is actually the right design, and the only argument is which of the above two methods is "better" in terms of the criteria listed above (handles, thread time).

It still doesn't matter.

Method A has one fewer handle, but one more flag. So the total number of things you have to keep track of is the same either way.

"Oh, but I save the overhead of an additional handle."

Dude, you're already burning a thread. A single handle to an event is noise compared to the cost of a thread.

"But I save the cost of validating the handle and following the reference to the underlying kernel object."

Dude, you're about to go to sleep for 50 milliseconds. Saving a few thousand clocks is noise compared to 50 milliseconds.

The flag method does have some other problems, none of which are deal-breaking, but are things to bear in mind.

First, that flag that you're checking. There's no synchronization on that variable, so the background thread may run a smidge longer than necessary because the change hasn't yet propagated to the CPU running the loop. Similarly, the sleep loop does take a little longer to notice that it should stop working. If the fKeepGoing flag is set to FALSE during the sleep, the sleep will still run to completion before the loop finds out.

In the grand scheme of things, however, the extra 50 to 100 milliseconds are probably not a big deal. The background thread is a little slow to shut down, that's all. The user will probably not even notice that the CPU meter was higher than normal for an additional tenth of a second. After all, the typical human reaction time is 100 milliseconds anyway.

I'm assuming that the code that signals the background thread doesn't sit around waiting for the background thread to clean up. If it does, then this 100ms delay may start to combine with other delays to turn into something the user may start to notice. A tenth of a second here, a tenth of a second there, soon you may find yourself accumulating a half second's delay, and that's a delay the human brain can perceive.

Comments (34)
  1. Dan says:

    Good to know I’m doing things right. :)

    Reminds me of a strange experience I’ve had with Sleep() though.  Sometimes I need to poll and wait for an event on another thread to finish (or an asynchronous event such as a response to a network request) before I can continue, though, and so I choose to use the Sleep method myself.  Interestingly enough, simply using Sleep(0) to yield execution to another thread results in high CPU usage:

    Dim timeout As TimeSpan = somevalue

    Dim timeoutat As Date = Date.Now + timeout

    While operationnotcomplete AndAlso Date.Now < timeoutat


    End While

    Sorry for the VB.NET, and the .NET in general, I know this is not a .NET blog but hey I figure that Sleep function just wraps the WinAPI Sleep anyway.

    Anyways, I never did figure out the high CPU usage, unless it’s simply because my CPU didn’t have anything better to do than run this while loop repeatedly, querying the system time every iteration.  Changing the sleep period to 10ms was more than enough to bring down the CPU usage without any noticeable delays.

  2. acq says:

    I don’t quite understand why you want to pause every so often. Why not just do the work at low priority?

    I’m not the author of the question but I followed your link.  Francois’ quote is:

    while( fKeepGoing )


    //Check something



    so if I understand him, he wants only to "check" something every 50 ms. I assume most of the times that check will say "nothing new" and once in a while it will decide to do some more work.

    What is it that he checks? I don’t know, I know that having a callback is better design when possible, and that Win32 can actually really notify for some events properly so that he doesn’t have to put that small 50 ms constant in

    WaitForSingle( hEvent, 50 )

    But as an illustration of his direction, I remember as I was impressed to discover:

    Running a Script Based on an Event


    It sounded just too good to be true. And it was.

    When I searched more I’ve seen that the event there is not really an event but polling where "WITHIN 5 " means "run the query every 5 seconds." At least the interface is in seconds, and the implementation maybe doesn’t have to access the hard disk, so maybe it’s actually still good enough to conserve battery power on the notebook. I’ve never investigated further.

  3. Joseph Koss says:

    It seems to me that there is some justification for the methodology.

    You (A) want to use less CPU, but (B) want some real CPU time so that the job does get done reasonably quickly.

    Going low priority could completely starve the thread of cpu time, at least temporarily, and I’m not really sure what limits are placed on that. Is it concievable that a low priority thread could go for several seconds without any attention? Several minutes?

  4. acq says:

    Dan: "another thread to finish (or an asynchronous event such as a response to a network request)"

    Both things can be done using the real WaitFor… calls or whatever the .NET equivalents for that call are, I’m certain tath they must exist. You shouldn’t use polling for something that doesn’t have to be polled at all.

  5. Sunil Joshi says:

    In my debug builds, I do this when I want code to wait until I attach the debugger.

    while (!IsDebuggerPresent ()) Sleep (1000);

    __debugbreak ();

  6. Karellen says:

    @Joseph: How long a low priority thread can wait for CPU time is probably entirely dependent on the quality and fairness of the scheduler in question. That is almost certainly a "real" implementation detail that doesn’t have much in the way of back-compat requirements, and is therefore likely to change significantly between different versions of Windows.

    More recent kernels are probably fairer than older ones. e.g. NT6+ (Vista and later) tracks cpu usage by cycle count rather than by time intervals as older versions (NT5.x-) did.

    Aside from that, I’m not aware of much detail having been released on Windows’ schedulers, so you’ll probably have to do your own benchmarking to find out.

  7. Gabe says:

    Another possibility is that the questioner was wondering whether using Sleep was more efficient than WaitFor. And I believe the answer is that Sleep is implemented as a call to WaitFor, so there is no difference.

    As for why somebody might want to do this, there are many possible things you might want to poll. One example is checking to see if a file on the network has changed. Although Windows has an API to notify you when a directory changes, network fileservers are under no obligation to support it, so you may have to poll.

  8. Dave O says:

    @Dan: Sleep(0) will do nothing if there’s no other thread ready to run on that CPU core. So it will help reduce CPU usage of a thread when there’s other competing threads, but it won’t yield to idle. You have to give the system some hint as to how much time you want to yield if you want to do that (or some event on which you want to do so and use WaitFor*).

    I believe the most basic option would be to use SwitchToThread() to give up the timeslice (essentially, WaitFor(next_tick) ).

    Otherwise you need to estimate the time you want to yield for (and maybe mess about with timeBeginPeriod if this is down around the scheduling quantum – e.g. for frame sync in games or, worse, emulation, although I keep hoping to find out about a better method for doing that…)

  9. Mike says:

    Anyways, I never did figure out the high CPU usage, unless it’s simply because my CPU didn’t have anything better to do than run this while loop repeatedly, querying the system time every iteration.

    Sleep( 0 ) only discards your quantum of the CPU. When no other thread is wainting to run, your thread will be the next to run.

    Idle is never executed when another thread may run.

  10. porter says:

    If you have just a "Sleep" in your production code and no other way of waking up that thread then in my book that is a poor solution.

    The trick to getting a system performing well, is to not do anything as efficiently as possible in order to get out of the way, and to be ready to start doing your thing as soon as the conditions are right.

    The one forgotten about is also to stop doing it when you are no longer required, eg application shutdown, do we have to wait for all these sleeps to expire before the process can exit?

  11. Adrian says:

    Polling is generally bad compared to being awakened when an interesting event happens, but there are legitimate reasons to want to have a thread do work, sleep, and repeat.

    If you have one thread cranking through a simulation, and you want to have another thread update the UI to give the user a sense of progress, then the work-sleep-repeat pattern makes sense.  There’s no point in updating the UI faster than a human can appreciate the changes.  Making the visualization thread low-priority would make the UI jerky, assuming the normal-priority threads ever relinquish control.

    Also, the 100 ms figure quoted as reaction time seems a bit low.  Wikipedia says human reaction times are often more than double that.  I have heard 100 ms described as the maximum time the UI should take to respond to a user action before the UI starts to feel hesitant.

  12. Mike says:

    One place I’ve seen similar code is in games that are framerate-locked.  Although in that case you would (hopefully) be waiting for a variable amount of time rather than a hard-coded amount.

    Whether or not it’s useful or harmful in the long run people do frequently complain about 100% cpu usage.  Sometimes were forced to fix the perception of a problem in addition to real problems.

  13. Joseph Koss says:

    In regards to sleep(0), it should be noted that it will not yield to lower priority threads (at least under normal circumstances.)

  14. Dave O says:

    Adrian: "the 100 ms figure quoted as reaction time seems a bit low.  Wikipedia says human reaction times are often more than double that.  I have heard 100 ms described as the maximum time the UI should take to respond to a user action before the UI starts to feel hesitant."

    Perception time != reaction time. 100ms is probably a good ballpark, but it depends on the situation, particularly if there’s sound involved.

    If you’re watching a video with sound sync problems you can perceive errors as low as 50ms. And Guitar Hero on a HDTV with 60ms lag is bad enough. 100ms would be a nightmare!

  15. Joseph Koss says:


    Indeed it is gameloops that I was thinking of with my suggestion that low priority threads were sometimes unacceptable.

    A fixed-step physics thread and an interpolating-renderer thread.

    The rendering thread should run full steam as much as possible, but the physics thread needs to idle from time to time if its getting too far ahead of “real time.”

    [Synchronization against wall-clock time is clearly not the issue in the original question. My comments clearly do not apply to gameloops, but I didn’t realize people would interpret that they were intended to. -Raymond]
  16. Van says:


    A lot of games engines use co-routines (using fibers if they’re on xbox) and just yield to another thread instead of having a timeout.

  17. sascha says:

    a spellchecker that consumes 100% cpu in a low priority thread can be quite a nuisance when running in a vm or other shared environment.

    it also makes it more complicated for power management with a dynamic frequency scaling cpu.

  18. Dean Harding says:

    “if the user accidentally changes the process priority from low to real-time”

    What the…? How does a user “accidentally” change a process priority from low to real-time? Especially when you can see in Task Manager that it’s already consuming 100% (or near 100%) CPU time!

    [If you’re going to worry about the user screwing with your process, you have bigger things to worry about. What if the user accidentally terminates the thread? What if the user accidentally suspends the UI thread? What if the user accidentally VirtualFree’s your process heap? -Raymond]
  19. mythbuster says:

    If it’s single time rare occurance I would agree with the 0-200 ms area figure to not being very perceivable. But lets suppose it’s something more frequent. Such as opening the explorer. Suppose for years you’ve seen the window pop in 66 ms and then someone at MS decides to add some features that triple that time to around 200 ms.

    And remember, pressing a key you hear a sound coming from hitting it so that’s the start point of the measurement, not when explorer receives the command.

  20. mythbuster says:

    a spellchecker that consumes 100% cpu in a low priority thread can be quite a nuisance when running in a vm or other shared environment.

    same goes for defraggers in Vista and Win7 that think the user is idle when he may be actually doing streaming video capture or playing a software music instrument.

  21. Dave Bacher says:

    Use the multimedia timers with the periodic flag in order to limit frame rate:


    Sleep and WaitFor don’t tell Windows your intent; the MM Timer with the periodic flag does, and so Windows knows you are trying to run at 20fps (50ms interval), and does its best to invoke your function every 50ms.

    If you use the WaitFor approach, you would run WaitFor and check the result.  For a time out result, you would run your loop.  That way, you could create the hEvent in your main loop, and then set it when it is time for the other loop to terminate.  You wouldn’t be "wasting" a handle — because you need a way to signal that thread to exit in order to terminate it, and an event handle would be the right way to signal it to exit.

    I would personally not use the Sleep approach, because the WaitFor approach is going to be safer.

    With all 3 approaches, you have to start off by computing how much time has actually passed.  Even the MM timer is just a "best effort," and you don’t know what else the user is doing; they could be transcoding all of pirate bay to 32×32 MP4 files to play on their iWatch in the background, and Windows might just flat out not be able to keep up. :)

  22. Lio says:

    "Which is better, hammering with a screwdriver or hammering with pliers?"

    Hammering with pliers, no contest.

  23. nksingh says:

    One note on Sleep(0) and SwitchToThread(), since some of the comments were mistaken:

    Both of these calls end up yielding execution to any thread which is ready to run on the current processor, regardless of the priority relation (on a multi-proc machine, threads waiting on other processors do not count). This is the behavior as of Vista and Win7. Earlier OSes had slightly different behaviors with regard to priority. Sleep(0)/SwitchToThread() is a generally pretty useless operation, so I wouldn’t encourage doing it.

    From the perspective of efficiency of doing this unfortunately inefficient action, Sleep(50) is marginally better than a wait.

  24. Igor Levicki says:

    >>Why not just do the work at low priority?<<

    Good luck interrupting such a thread if the user accidentally changes the process priority from low to real-time class.

    I personally hate polling but one question remains unanswered — how would you check for things which do not have notification mechanism exposed except by polling?

    For example, you need to sit there in the background and wait for a program to finish writing to a file and close the handle so you can move it out to some other folder, send it via email, burn to a CD, whatever.

    There is ReadDirectoryChangesW() all right, but thanks to ingenious shell developers there is no such thing as FILE_NOTIFY_CHANGE_CLOSE (nor OPEN apart from creation).

    The only thing you can do is poll(*) and when you are already forced to do it due to the stupid OS design, then you might take care to use as little resources as possible.

    So instead of ranting it would be better to give an answer which of the two polling methods is more efficient and less resource consuming from the OS point of view.

    [Um, there’s a second half to the article. You might want to try reading that part too. And you wonder why I get frustrated at comments. “Hey, you jerk, instead of doing X, why not do Y?” Um, I did do Y. -Raymond]

    * – yes, you can also write a filesystem filter driver or a kernel mode driver which hooks CloseHandle(), but that is completely out of scope because it complicates otherwise very simple task. Or a task which would be simple if there was a proper notification for you to subscribe to.

  25. Worf says:

    Using WaitFor and an event handle can be more efficient if you can slow down your poll rate. For example, in checking a network drive, instead of polling once a second, why not poll every 5? The user probably won’t notice that it took "that long" for it to discover the change, and you poll 5 times less frequently.

    The event can be used to signal shutdown – so the thread exits immediately rather than when the sleep expires – a more important consideration as you spend more and more time in sleep.

    E.g., say you’re polling for e-mail. If you poll once every 10 minutes, a sleep solution will mean the user may have to wait 10 minutes for the thread to shutdown, while WaitFor will have it exiting quickly.

  26. Igor Levicki says:

    >>Um, there’s a second half to the article. You might want to try reading that part too.<<

    I did but only the first part stuck with me :)

    >>And you wonder why I get frustrated at comments.<<

    You get frustrated by comments, people get frustrated with Windows. Personally, I think you got better part of a deal ;)

    [I’m flattered by the suggestion that I’m responsible for all of Windows, but alas my paycheck doesn’t reflect that. (You must be a lot of fun at social events. “Nice to meet you. Oh, you work for company X? I will now be unpleasant towards you.”) But we’ll play it your way: Since I’m not interested in backward compatibility with your earlier comments, I’ll just uninstall your comments. (P.S., you’re supposed to say that Vista sucks.) -Raymond]
  27. Jonathan says:

    How does a tool like Perfmon work? I would’ve thought it would work by polling performance counters using a windows timer, or a thread with Sleep or WaitForMultipleObjects. Is there a better way?

  28. Mike Dimmick says:

    @Jonathan: performance counters do have to be measured on a periodic basis with a Windows timer (for example), as there is no way for a performance counter DLL to say that its value has changed – and you wouldn’t want the service to have to wait to tell any viewers that something had occurred!

    The performance counter model is that (usually at least) the counts always increase, and the application presenting the data does the division into ‘per second’. So if I have a ‘requests/sec’ counter, I tell Windows that it’s a PERF_COUNTER_RATE counter, then add one to it every time I handle a request. Perfmon remembers what the last sample value was, subtracts it from my new value, and divides by the sample period to display the rate.

  29. Joseph Koss says:


    Thats not true about sleep(0) according to MSDN:

    "A value of zero causes the thread to relinquish the remainder of its time slice to any other thread of equal priority that is ready to run. If there are no other threads of equal priority ready to run, the function returns immediately, and the thread continues execution."

    This is also documented the same for sleepEx(0)

  30. tony says:

    I often use polling of serial ports for example.

  31. Alexandre Grigoriev says:

    @Joseph Koss,

    nksingh said that the behavior changed in Vista+, where the thread will relinquish the timeslice to threads even of lower priority. Supposedly, that makes badly designed apps more cooperative.

  32. porter says:

    > I often use polling of serial ports for example.

    Why? You can used overlapped ReadFile.

  33. Arno says:

    It hasn’t been mentioned: If fKeepGoing is accessed by another thread, it must be declared volatile. Otherwise the code is incorrect.

  34. peterchen says:

    The query operation itself might be comparedly costly, or hit a limited ressource other than CPU.

Comments are closed.

Skip to main content