{"id":17353,"date":"2009-07-27T10:00:00","date_gmt":"2009-07-27T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2009\/07\/27\/polling-by-sleeping-versus-polling-by-waiting-with-a-timeout\/"},"modified":"2009-07-27T10:00:00","modified_gmt":"2009-07-27T10:00:00","slug":"polling-by-sleeping-versus-polling-by-waiting-with-a-timeout","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20090727-00\/?p=17353","title":{"rendered":"Polling by sleeping versus polling by waiting with a timeout"},"content":{"rendered":"<p>\nCommenter Francois Boucher asks\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/pages\/407234.aspx#631569\">\nit&#8217;s better to write a background worker thread that polls with\n<code>Sleep()<\/code> and a flag, or polls by waiting for an event\nwith a timeout<\/a>?\n<\/p>\n<pre>\n\/\/ method A\nwhile (fKeepGoing) {\n .. a little work ..\n Sleep(50);\n}\n\/\/ method B\ndo {\n .. a little work ..\n} while (WaitForSingleObject(hEvent, 50) == WAIT_TIMEOUT);\n<\/pre>\n<p>\n&#8220;Which scenario is better?\nThe first one uses only 1 handle for the thread.\nThe second one will use 2.\nBut is the first scenario wasting more thread time?\nIs it worth using the event (kernel object)?&#8221;<\/p>\n<p>\nYeah, whatever.\n<\/p>\n<p>\nI don&#8217;t quite understand why you want to pause every so often.\nWhy not just do the work at low priority?\nWhen there are more important things to do, your background thread\nwill stop doing whatever it&#8217;s doing.\nWhen there is an available CPU, then your background thread\nwill do its thing as fast as it can (until something with higher\npriority arrives).\n<\/p>\n<p>\nThe only thing I can think of is that by adding the pauses,\nyour program won&#8217;t look like it&#8217;s consuming 100% CPU while the\nbackground processing is going on.\nWhich is true, but then again,\nthat&#8217;s not much consolation.\n&#8220;Wow, with these changes,\nmy spell check takes only 10% of the CPU.\nBut then again, it also takes 10 times as long.&#8221;\nIs that an improvement?\nYou made your customer wait ten times as long for the document to\nbe spell checked.\nThat&#8217;s ten times less battery life for your laptop.\n<\/p>\n<p>\nAnd generally speaking, polling should be avoided because it\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2006\/01\/24\/516808.aspx\">\ncarries negative consequences for system performance<\/a>.\nSo we&#8217;re basically asking, &#8220;Which is better, hammering with a screwdriver\nor hammering with pliers?&#8221;\n<\/p>\n<p>\nBut let&#8217;s say for the sake of argument that this &#8220;back off periodically&#8221;\npolling loop is actually the right design, and the only argument is\nwhich of the above two methods is &#8220;better&#8221; in terms of the criteria\nlisted above (handles, thread time).\n<\/p>\n<p>\nIt still doesn&#8217;t matter.\n<\/p>\n<p>\nMethod&nbsp;A has one fewer handle, but one more flag.\nSo the total number of things you have to keep track of is the same\neither way.\n<\/p>\n<p>\n&#8220;Oh, but I save the overhead of an additional handle.&#8221;\n<\/p>\n<p>\nDude, you&#8217;re already burning a thread.\nA single handle to an event is noise compared to the cost of a thread.\n<\/p>\n<p>\n&#8220;But I save the cost of validating the handle and following the\nreference to the underlying kernel object.&#8221;\n<\/p>\n<p>\nDude, you&#8217;re about to go to sleep for 50&nbsp;<i>milliseconds<\/i>.\nSaving a few thousand clocks is noise compared to 50&nbsp;milliseconds.\n<\/p>\n<p>\nThe flag method does have some other problems, none of which are\ndeal-breaking, but are things to bear in mind.\n<\/p>\n<p>\nFirst, that flag that you&#8217;re checking.\nThere&#8217;s no synchronization on that variable, so the background thread\nmay run a smidge longer than necessary because the change hasn&#8217;t\nyet propagated to the CPU running the loop.\nSimilarly,\nthe sleep loop does take a little longer to notice that it should\nstop working.\nIf the <code>fKeepGoing<\/code> flag is set to <code>FALSE<\/code>\nduring the sleep,\nthe sleep will still run to completion before the loop finds out.\n<\/p>\n<p>\nIn the grand scheme of things, however, the extra 50 to 100 milliseconds\nare probably not a big deal.\nThe background thread is a little slow to shut down,\nthat&#8217;s all.\nThe user will probably not even notice that the CPU meter was higher\nthan normal for an additional tenth of a second.\nAfter all, the typical human reaction time is 100 milliseconds anyway.\n<\/p>\n<p>\nI&#8217;m assuming that the code that signals the background thread doesn&#8217;t\nsit around waiting for the background thread to clean up.\nIf it does, then this 100ms delay may start to combine with other\ndelays to turn into something the user may start to notice.\nA tenth of a second here, a tenth of a second there, soon you may\nfind yourself accumulating a half second&#8217;s delay, and that&#8217;s a delay\nthe human brain can perceive.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Commenter Francois Boucher asks it&#8217;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 .. Sleep(50); } \/\/ method B do { .. a little work .. } while (WaitForSingleObject(hEvent, [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-17353","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Commenter Francois Boucher asks it&#8217;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 .. Sleep(50); } \/\/ method B do { .. a little work .. } while (WaitForSingleObject(hEvent, [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/17353","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=17353"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/17353\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=17353"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=17353"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=17353"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}