{"id":109738,"date":"2024-05-09T07:00:52","date_gmt":"2024-05-09T14:00:52","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=109738"},"modified":"2024-05-09T14:00:21","modified_gmt":"2024-05-09T21:00:21","slug":"20240509-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20240509-52\/?p=109738","title":{"rendered":"Asking for a DispatcherQueue from a GUI thread you created"},"content":{"rendered":"<p>The most common way to create a <code>Dispatcher\u00adQueue<\/code> is to ask for one to be created on a dedicated thread by calling <code>Dispatcher\u00adQueue\u00adController.<wbr \/>Create\u00adOn\u00adDedicated\u00adThread<\/code>. But another way to create a <code>Dispatcher\u00adQueue<\/code> is to ask for one to be attached to an existing message queue.<\/p>\n<pre>DispatcherQueueOptions options{\r\n    sizeof(options),\r\n    DQTYPE_THREAD_CURRENT,\r\n    DQTAT_COM_NONE\r\n};\r\n\r\nwinrt::com_ptr&lt;ABI::Windows::System::IDispatcherQueueController&gt; controller;\r\nwinrt::check_hresult(CreateDispatcherQueueController(options, controller.put()));\r\n<\/pre>\n<p>If you ask <code>Create\u00adDispatcher\u00adQueue\u00adController<\/code> to create a a <code>DQTYPE_<wbr \/>THREAD_<wbr \/>CURRENT<\/code>, then it will create a dispatcher queue that is attached to the current thread&#8217;s message queue. This dispatcher queue does not have its own message pump; it&#8217;s relying on the thread&#8217;s existing message pump to do the work.<\/p>\n<p>Attaching a dispatcher queue to an existing message queue is convenient if you have existing Win32-style code, and you want to integrate it with components that need a dispatcher queue: You can create your Win32 thread in the traditional way, set up a message pump, and then ask for a dispatcher queue to be attached to it.<\/p>\n<p>Note that when you do this, it becomes your responsibility to keep the thread alive and pumping messages until the dispatcher queue has been shut down. There are a few ways of knowing when the shutdown has completed.<\/p>\n<p>One is to await the <code>Shutdown\u00adQueue\u00adAsync<\/code> call. Its <code>IAsync\u00adAction<\/code> completes when the shutdown is complete. After the completion of that operation, you can post a message to the message queue to tell it that it&#8217;s safe to exit. (You might even use <code>Post\u00adQuit\u00adMessage<\/code> to do that.)<\/p>\n<pre>winrt::fire_and_forget OnDestroy()\r\n{\r\n    co_await m_controller.ShutdownQueueAsync();\r\n    PostQuitMessage(0);\r\n}\r\n<\/pre>\n<p>Another way is to register a handler for the dispatcher queue&#8217;s <code>Shutdown\u00adCompleted<\/code> event and post the &#8220;safe to exit&#8221; message from there.<\/p>\n<pre>void OnDestroy()\r\n{\r\n    m_controller.ShutdownCompleted([](auto&amp;&amp;, auto&amp;&amp;) {\r\n        PostQuitMessage(0);\r\n    });\r\n    m_controller.ShutdownQueueAsync();\r\n}\r\n<\/pre>\n<p>This trick works because all dispatcher queue events are raised from the dispatcher queue thread, so the <code>Post\u00adQuit\u00adMessage<\/code> posts back into the correct thread.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Grafting a DispatcherQueue onto an existing thread.<\/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-109738","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Grafting a DispatcherQueue onto an existing thread.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109738","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=109738"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109738\/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=109738"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=109738"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=109738"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}