{"id":104911,"date":"2021-02-26T07:00:00","date_gmt":"2021-02-26T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=104911"},"modified":"2021-03-08T11:53:07","modified_gmt":"2021-03-08T19:53:07","slug":"20210226-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20210226-00\/?p=104911","title":{"rendered":"What does error E_ILLEGAL_DELEGATE_ASSIGNMENT mean?"},"content":{"rendered":"<p>A customer reported that they program was crashing because it got the error <code>E_<wbr \/>ILLEGAL_<wbr \/>DELEGATE_<wbr \/>ASSIGNMENT<\/code>. The description of this error is &#8220;A delegate was assigned when not allowed,&#8221; but what does that mean?<\/p>\n<p>The most common source of this error is attempting to set a completion callback for a Windows Runtime <code>IAsyncXxx<\/code> asynchronous operation when a callback has already been set. There can be only one completion callback for an asynchronous operation, and you get this error if you try to set a second one.<\/p>\n<p>You typically do not set completion callbacks explicitly. They are usually set for you as part of your programming framework. In the case of C++\/WinRT, the most common place it it happens is when you <code>co_await<\/code> an asynchronous operation. (Less common sources are functions like <code>when_all<\/code> or <code>when_any<\/code>.)<\/p>\n<p>The good news is that the stack trace from the crash dump usually points to the code that attempted to register the second callback.<\/p>\n<pre>SomeClass::SomeClass()\r\n{\r\n    m_start = StartAsync();\r\n}\r\n\r\nIAsyncAction SomeClass::DoThing1Async()\r\n{\r\n    co_await m_start;\r\n    Thing1();\r\n}\r\n\r\nIAsyncAction SomeClass::DoThing2Async()\r\n{\r\n    co_await m_start; \/\/ \u2190 crash here\r\n    Thing2();\r\n}\r\n<\/pre>\n<p>The idea here is that the object initializes itself at construction, but does so asynchronously. When the <code>Do\u00adThing<\/code> methods are called, they first wait for the initialization to complete, and then proceed with the actual operation.<\/p>\n<p>The problem is that we are <code>co_await<\/code>ing the <code>m_start<\/code> object more than once. Each coroutine&#8217;s call to <code>co_await<\/code> will try to set its own continuation as the completion handler so it can resume execution when the operation completes. The first one to perform the <code>co_await<\/code> succeeds. The rest fail with <code>E_<wbr \/>ILLEGAL_<wbr \/>DELEGATE_<wbr \/>ASSIGNMENT<\/code>.<\/p>\n<p>The rule that we walk away with is &#8220;Each <code>IAsyncXxx<\/code> can be awaited only once.&#8221;<\/p>\n<p>Okay, so what do we do if we need to await something more than once, like here, where we want all of the operations to wait for the initialization to complete before proceeding with work?<\/p>\n<p>You&#8217;ll have to find something that can be awaited more than once.<\/p>\n<p>We&#8217;ll look into possible solutions next time.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A delegate was assigned when not allowed, but when is it allowed?<\/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":[],"class_list":["post-104911","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing"],"acf":[],"blog_post_summary":"<p>A delegate was assigned when not allowed, but when is it allowed?<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/104911","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=104911"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/104911\/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=104911"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=104911"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=104911"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}