{"id":91501,"date":"2015-09-28T07:00:00","date_gmt":"2015-09-28T21:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20150928-00\/?p=91501\/"},"modified":"2019-03-13T12:19:59","modified_gmt":"2019-03-13T19:19:59","slug":"20150928-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20150928-00\/?p=91501","title":{"rendered":"What happens to lost timer messages if I don&#8217;t process them fast enough?"},"content":{"rendered":"<p>Some time ago, I noted that <a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2014\/12\/04\/10577881.aspx\">if your <code>WM_TIMER<\/code> handler takes longer than the timer period, your queue will not fill up with <code>WM_TIMER<\/code> messages<\/a>. The <code>WM_TIMER<\/code> message is generated on demand, and if your handler doesn&#8217;t check for messages, then there is no demand for timer messages. But what happens when your thread finally starts processing messages again? What happens to the timers that elapsed while you were busy? Do they accumulate? <\/p>\n<p>Here&#8217;s a sketch of how timers work. (Note that the timers under discussion here are the timers set by the <code>Set&shy;Timer<\/code> function.) <\/p>\n<p>When a timer is created, it is initially <i>not ready<\/i>. <\/p>\n<p>Every <var>n<\/var> milliseconds (where <var>n<\/var> is the period of the timer), the timer is marked <i>ready<\/i>. This is done regardless of the state of the UI thread. Note that <i>ready<\/i> is a flag, not a counter. If the timer is already ready, then it stays ready; there is no such thing as &#8220;double ready&#8221;. The <code>QS_TIMER<\/code> flag is set on the queue state, indicating that there is now a pending timer for the thread. This in turn may cause a function like <code>Get&shy;Message<\/code> or <code>Msg&shy;Wait&shy;For&shy;Multiple&shy;Objects<\/code> to wake up. <\/p>\n<p>When the appropriate conditions are met (<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2011\/12\/19\/10249000.aspx\">as discussed earlier<\/a>), the window manager checks whether there are any timers for the thread that are marked <i>ready<\/i>. If so, then the corresponding <code>WM_TIMER<\/code> message is generated and the <i>ready<\/i> flag is cleared. <\/p>\n<p>Let&#8217;s illustrate this with our <a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2003\/07\/23\/54576.aspx\">scratch program<\/a>. Make the following changes: <\/p>\n<pre>\n#include &lt;strsafe.h&gt;\n\nDWORD g_tmStart;\n\nvoid SquirtTime()\n{\n TCHAR sz[256];\n StringCchPrintf(sz, 256, \"%d\\r\\n\", GetTickCount() - g_tmStart);\n OutputDebugString(sz);\n}\n<\/pre>\n<p>This adds a function that prints the number of milliseconds which have elapsed since <code>g_tmStart<\/code>. Note that we use simple subtraction and rely on unsigned arithmetic to handle timer rollover issues. <\/p>\n<pre>\nvoid CALLBACK OnTimer(HWND hwnd, UINT, UINT_PTR, DWORD)\n{\n SquirtTime();\n}\n<\/pre>\n<p>Our timer tick handler merely prints the elapsed time to the debugger. <\/p>\n<pre>\nBOOL\nOnCreate(HWND hwnd, LPCREATESTRUCT lpcs)\n{\n <font COLOR=\"blue\">g_tmStart = GetTickCount();\n SetTimer(hwnd, 1, 500, OnTimer);\n Sleep(1750);<\/font>\n return TRUE;\n}\n<\/pre>\n<p>Finally, we create a 500ms timer on our window, but we also intentionally stall the thread for 1750ms. <\/p>\n<p>Can you predict the output of this program? <\/p>\n<p>Here&#8217;s what I got when I ran the program:<\/p>\n<pre>\n1797\n2000\n2500\n3000\n3500\n4000\n4500\n...\n<\/pre>\n<p>Let&#8217;s see if we can explain it. <\/p>\n<p>Since the timer is set to fire at 500ms intervals, every 500ms, the timer gets marked ready. <\/p>\n<ul>\n<li>At <var>T<\/var> = 500ms, the timer is marked ready. \n<li>At <var>T<\/var> = 1000ms, the timer is marked ready.     This is redundant, since the timer is already ready. \n<li>At <var>T<\/var> = 1500ms, the timer is marked ready.     Again, this is redundant. \n<li>At <var>T<\/var> = 1750ms, the program finally wakes up     from its <code>Sleep<\/code> and eventually gets around     to processing messages. \n<li>Hey look, there is a ready timer, so we generate a     <code>WM_TIMER<\/code> message and clear the <i>ready<\/i>     flag. \n<li>At <var>T<\/var> = 1797ms, the timer message is processed. \n<li>The program returns to its message loop, where there are no     further messages to process, so it sits and waits. \n<li>At <var>T<\/var> = 2000ms, the timer is marked ready.     This causes the <code>Get&shy;Message<\/code> to wake up     generate a     <code>WM_TIMER<\/code> message and clear the <i>ready<\/i>     flag. \n<li>At <var>T<\/var> = 2000ms, the timer message is processed. \n<li>At <var>T<\/var> = 2500ms, the timer is marked ready.     This causes the <code>Get&shy;Message<\/code> to wake up     generate a     <code>WM_TIMER<\/code> message and clear the <i>ready<\/i>     flag. \n<li>At <var>T<\/var> = 2500ms, the timer message is processed. \n<li>And so on, with a new timer message every 500ms     that is processed immediately. <\/ul>\n<p>Observe that when the program begins processing messages at <var>T<\/var> = 1750ms, it receives only one timer message right away, even though three timer periods have elapsed. <\/p>\n<p>I guess another way of looking at this is to think of your timer as setting a frame rate. If your thread is busy when it&#8217;s time to render the next frame, then the next frame is late. And if your thread is really busy, it may drop frames entirely. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>They never existed.<\/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-91501","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>They never existed.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/91501","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=91501"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/91501\/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=91501"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=91501"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=91501"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}