{"id":95855,"date":"2017-03-29T07:00:00","date_gmt":"2017-03-29T21:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=95855"},"modified":"2019-03-13T01:08:48","modified_gmt":"2019-03-13T08:08:48","slug":"20170329-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20170329-00\/?p=95855","title":{"rendered":"A brief discussion on how best to respond to the end-session messages"},"content":{"rendered":"<p>A customer discovered that their application&#8217;s shutdown code sometimes deadlocked. To address the problem, they moved the bulk of their shutdown code to the <code>WM_END&shy;SESSION<\/code> message handler. The customer found <a HREF=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20130627-00\/?p=3973\">my earlier discussion of the <code>WM_END&shy;SESSION<\/code> message<\/a> and wondered if they were doing the right thing. <\/p>\n<p>Yes, it&#8217;s okay to do shutdown activities in response to the <code>WM_END&shy;SESSION<\/code> message, provided that the <code>wParam<\/code> is nonzero, indicating that the session really is ending. If the <code>wParam<\/code> is zero, then it means that the session is <i>not<\/i> ending, so you had better not destroy anything you still need. <\/p>\n<p>Recall the shutdown sequence: First, the application receives a <code>WM_QUERY&shy;END&shy;SESSION<\/code> message. Here is the traditional point at which you can display a prompt to ask the user whether they want to save their unsaved changes.&sup1; Normally, you return <code>TRUE<\/code>, but if the user hits <i>Cancel<\/i> or otherwise indicates that they don&#8217;t want to shut down after all, then you return <code>FALSE<\/code>. <\/p>\n<p>If you returned <code>TRUE<\/code>, then you will eventually receive a <code>WM_END&shy;SESSION<\/code> message whose <code>wParam<\/code> indicates whether the session really is ending. (The session might not actually be ending if another application returned <code>FALSE<\/code> to the <code>WM_QUERY&shy;END&shy;SESSION<\/code> message, or if the user canceled shutdown from the UI.) <\/p>\n<p>The customer shared some of their code, and I noticed that they were destroying a window in their <code>WM_END&shy;SESSION<\/code> message handler, which is suspicious for two reasons: <\/p>\n<ol>\n<li>    If the <code>wParam<\/code> is <code>FALSE<\/code>,     the application will continue to run, but it lost     one of its windows! <\/li>\n<li>    If the <code>wParam<\/code> is <code>TRUE<\/code>,     then it&#8217;s okay to destroy things, but remember that     you are running under a time constraint,     and     <a HREF=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20120105-00\/?p=8683\">    the building is being demolished<\/a>,     so you probably shouldn&#8217;t be wasting time sweeping     the floor and emptying the trash cans. <\/li>\n<\/ol>\n<p>What you could do is to kick off a background thread to prepare for shutdown when you receive the <code>WM_QUERY&shy;END&shy;SESSION<\/code> message. For example, you might start an autosave operation. Whatever you do, make sure that it&#8217;s okay for the operation to occur even if the shutdown is subsequently canceled. <\/p>\n<p>When you get the <code>WM_END&shy;SESSION<\/code> message, you wait until that background operation completes before telling the system, &#8220;I&#8217;m good; you can shut down now.&#8221; <\/p>\n<p>Opportunistically starting the operation when you get the <code>WM_QUERY&shy;END&shy;SESSION<\/code> message means that you can respond more quickly to the <code>WM_END&shy;SESSION<\/code> message. <\/p>\n<p>&sup1; In practice, displaying a prompt is usually not a good idea because if you don&#8217;t respond to the message after a few seconds, the system will shut down without you. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>You can start early, but be aware that the user might change their mind.<\/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-95855","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>You can start early, but be aware that the user might change their mind.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/95855","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=95855"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/95855\/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=95855"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=95855"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=95855"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}