{"id":106475,"date":"2022-04-13T07:00:00","date_gmt":"2022-04-13T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=106475"},"modified":"2022-08-15T18:32:34","modified_gmt":"2022-08-16T01:32:34","slug":"20220413-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20220413-00\/?p=106475","title":{"rendered":"A survey of how implementations of Windows Runtime events deal with errors"},"content":{"rendered":"<p>There are three commonly-seen implementations of Windows Runtime events (one of which with four variants), and they deal with errors differently.<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th rowspan=\"2\">Class<\/th>\n<th colspan=\"5\">Disconnect<br \/>\nerrors<\/th>\n<th rowspan=\"2\">Behavior for other errors<\/th>\n<\/tr>\n<tr>\n<td style=\"vertical-align: middle; width: 1em;\"><span style=\"writing-mode: vertical-lr; transform: rotate(180deg);\"> <code>RPC_<wbr \/>E_<wbr \/>DISCONNECTED<\/code> <\/span><\/td>\n<td style=\"vertical-align: middle; width: 1em;\"><span style=\"writing-mode: vertical-lr; transform: rotate(180deg);\"> <code>RPC_<wbr \/>S_<wbr \/>SERVER_<wbr \/>UNAVAILABLE<\/code> <\/span><\/td>\n<td style=\"vertical-align: middle; width: 1em;\"><span style=\"writing-mode: vertical-lr; transform: rotate(180deg);\"> <code>RPC_E_SERVER_DIED<\/code> <\/span><\/td>\n<td style=\"vertical-align: middle; width: 1em;\"><span style=\"writing-mode: vertical-lr; transform: rotate(180deg);\"> <code>RPC_E_SERVER_DIED_DNE<\/code> <\/span><\/td>\n<td style=\"vertical-align: middle; width: 1em;\"><span style=\"writing-mode: vertical-lr; transform: rotate(180deg);\"> <code>JSCRIPT_<wbr \/>E_<wbr \/>CANTEXECUTE<\/code> <\/span><\/td>\n<\/tr>\n<tr>\n<td nowrap=\"nowrap\">\n<div><code>WRL::EventSource&lt;<\/code><\/div>\n<div style=\"text-align: right;\"><code>FireAll&gt;<\/code><\/div>\n<\/td>\n<td align=\"center\">\u2022<\/td>\n<td align=\"center\">\u2022<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td align=\"center\">\u2022<\/td>\n<td>Ignore errors.<\/td>\n<\/tr>\n<tr>\n<td nowrap=\"nowrap\">\n<div><code>WRL::EventSource&lt;<\/code><\/div>\n<div style=\"text-align: right;\"><code>StopOnFirstError&gt;<\/code><\/div>\n<\/td>\n<td align=\"center\">\u2022<\/td>\n<td align=\"center\">\u2022<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td align=\"center\">\u2022<\/td>\n<td>Stop on first handler to return an error and return that error.<\/td>\n<\/tr>\n<tr>\n<td nowrap=\"nowrap\">\n<div><code>WRL::EventSource&lt;<\/code><\/div>\n<div style=\"text-align: right;\"><code>ReportUnhandled-<\/code><\/div>\n<div style=\"text-align: right;\"><code>OnFirstError-<\/code><\/div>\n<div style=\"text-align: right;\"><code>WithWin8Quirk&gt;<\/code><\/div>\n<\/td>\n<td align=\"center\">\u2022<\/td>\n<td align=\"center\">\u2022<\/td>\n<td align=\"center\">\u2022<\/td>\n<td align=\"center\">\u2022<\/td>\n<td align=\"center\">\u2022<\/td>\n<td>For Win8 apps: Ignore errors.<br \/>\nOtherwise: Stop on first handler to return an error. Raise the <a href=\"https:\/\/docs.microsoft.com\/en-us\/uwp\/api\/windows.applicationmodel.core.coreapplication.unhandlederrordetected\"> <code>CoreApplication.<wbr \/>Unhandled\u00adError\u00adDetected<\/code><\/a> event. If handled, then return <code>S_OK<\/code>, else return the original error.<\/td>\n<\/tr>\n<tr>\n<td nowrap=\"nowrap\">\n<div><code>WRL::EventSource&lt;<\/code><\/div>\n<div style=\"text-align: right;\"><code>StopOnFirstError-<\/code><\/div>\n<div style=\"text-align: right;\"><code>WithWin8Quirk&gt;<\/code><\/div>\n<\/td>\n<td align=\"center\">\u2022<\/td>\n<td align=\"center\">\u2022<\/td>\n<td align=\"center\">\u2022<\/td>\n<td align=\"center\">\u2022<\/td>\n<td align=\"center\">\u2022<\/td>\n<td>For Win8 apps: Ignore errors.<br \/>\nOtherwise: Stop on first handler to return an error and return that error.<\/td>\n<\/tr>\n<tr>\n<td>C++\/CX <code>event<\/code><\/td>\n<td align=\"center\">\u2022<\/td>\n<td align=\"center\">\u2022<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td align=\"center\">\u2022<\/td>\n<td>Stop on first handler to return an error and return that error.<\/td>\n<\/tr>\n<tr>\n<td><code>winrt::event<\/code><\/td>\n<td align=\"center\">\u2022<\/td>\n<td align=\"center\">\u2022<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td align=\"center\">\u2022<\/td>\n<td>Ignore errors.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The code for <code>WRL::<wbr \/>Event\u00adSource<\/code> is in <code>wrl\/event.h<\/code>. The code for C++\/CX <code>event<\/code> is in <code>vccorlib.h<\/code>, where it is called <code>Platform::<wbr \/>Event\u00adSource<\/code>. And the code for C++\/WinRT <code>winrt::event<\/code> is in <code>winrt\/base.h<\/code>. I built the above table by reading the code. (You can do it too.)<\/p>\n<p>For WRL, the default for <code>Event\u00adSource<\/code> is <code>Fire\u00adAll<\/code> for third-party code, and <code>Report\u00adUnhandled\u00adOn\u00adFirst\u00adError\u00adWith\u00adWin8\u00adQuirk<\/code> for Windows operating system code.<\/p>\n<p>In all cases, a handler that returns one of the recognized Disconnect error codes is removed as an event handler and therefore will not receive any future events. (However, it will not be considered an error to decide whether or not to stop calling further handlers.) To avoid <a title=\"The secret signal that tells Windows Runtime events that the event recipient no longer exists\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20190521-00\/?p=102505\"> accidentally propagating one of these secret error codes<\/a> out of your event handler, wrap your event handler in a <code>try<\/code>\u2026<code>catch (...)<\/code> or mark your event handlers as <code>noexcept<\/code>.<\/p>\n<p>In fact, given that different event sources deal with errors differently, you probably should simply avoid returning errors from your event handler. Wrap the event handler in a <code>try<\/code>\u2026<code>catch (...)<\/code> so you can decide what to do in case of an error, or mark the event handler as <code>noexcept<\/code> to say that all errors are fatal to the application.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>All happy event delegates are alike; each unhappy event delegate is unhappy in its own way.<\/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-106475","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>All happy event delegates are alike; each unhappy event delegate is unhappy in its own way.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/106475","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=106475"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/106475\/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=106475"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=106475"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=106475"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}