{"id":103970,"date":"2020-07-09T07:00:00","date_gmt":"2020-07-09T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=103970"},"modified":"2020-07-09T07:20:51","modified_gmt":"2020-07-09T14:20:51","slug":"20200709-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20200709-00\/?p=103970","title":{"rendered":"Cancelling a Windows Runtime asynchronous operation, part 7: WRL-generated asynchronous operations"},"content":{"rendered":"<p>Last time, we saw that <a href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20200708-00\/?p=103968\"> if a C++\/WinRT asynchronous operation is cancelled, the result is an <code>hresult_<wbr \/>canceled<\/code>.<\/a> Today, we&#8217;ll look at another implementation library for asynchronous operations: The Windows Runtime Template Library (WRL).<\/p>\n<p>WRL is a bit out of fashion nowadays, but back in its heyday, it was the stuff everybody used for creating Windows Runtime objects and asynchronous operations.<\/p>\n<pre>class AsyncBase&lt; ... &gt; : ...\r\n{\r\n    inline HRESULT CheckValidStateForResultsCall()\r\n    {\r\n        Details::AsyncStatusInternal current = Details::_Undefined;\r\n        CurrentStatus(&amp;current);\r\n\r\n        if (current == Details::_Error)\r\n        {\r\n            ...\r\n        }\r\n\r\n        if (resultType == SingleResult)\r\n        {\r\n            if (current != Details::_Completed)\r\n            {\r\n                <span style=\"color: blue;\">::RoOriginateError(E_ILLEGAL_METHOD_CALL, nullptr);\r\n                return E_ILLEGAL_METHOD_CALL;<\/span>\r\n            }\r\n        }\r\n        ...\r\n    }\r\n};\r\n<\/pre>\n<p>The <code>Check\u00adValid\u00adState\u00adFor\u00adResults\u00adCall<\/code> method does what is says: It validates that the operation is in a correct state for a call to <code>Get\u00adResults()<\/code>. In the case where the operation has been canceled, we fail the first test (which propagates any explicit error code), but make it into the second part. This is a single-result operation\u00b9 and a cancelled operation is not complete, so it returns <code>E_<wbr \/>ILLEGAL_<wbr \/>METHOD_<wbr \/>CALL<\/code>, which propagates back into C++\/WinRT as <code>hresult_<wbr \/>illegal_<wbr \/>method_<wbr \/>call<\/code>.<\/p>\n<p>And that solves the mystery of why some cancelled operations throw an <code>hresult_<wbr \/>illegal_<wbr \/>method_<wbr \/>call<\/code> exception. It took us a week to get here, but we finally made it. The propagation of cancellation is a delicate dance between the the operation and the awaiter, and it&#8217;s easy to stumble.<\/p>\n<p>\u00b9 Nearly all Windows Runtime asynchronous operations are single-result. There&#8217;s another rarely-seen variant called the multiple-result asynchronous operation, which lets you call <code>Get\u00adResults<\/code> before the operation has completed, and it gives you the result-so-far. I am not aware of any operations that do this, but the code supports.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The library that came before.<\/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-103970","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>The library that came before.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/103970","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=103970"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/103970\/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=103970"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=103970"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=103970"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}