Browse Source

Don't ignore exceptions from async commands

Equbuxu 2 years ago
parent
commit
e872a214b9

+ 19 - 3
src/PixiEditor/Models/Commands/CommandController.cs

@@ -282,15 +282,31 @@ internal class CommandController
 
 
             var parameters = method?.GetParameters();
             var parameters = method?.GetParameters();
 
 
-            Action<object> action;
+            async void ActionOnException(Task faultedTask)
+            {
+                // since this method is "async void" and not "async Task", the runtime will propagate exceptions out if it
+                // (instead of putting them into the returned task and forgetting about them)
+                await faultedTask; // this instantly throws the exception from the already faulted task
+            }
 
 
+            Action<object> action;
             if (parameters is not { Length: 1 })
             if (parameters is not { Length: 1 })
             {
             {
-                action = x => method.Invoke(instance, null);
+                action = x =>
+                {
+                    object result = method.Invoke(instance, null);
+                    if (result is Task task)
+                        task.ContinueWith(ActionOnException, TaskContinuationOptions.OnlyOnFaulted);
+                };
             }
             }
             else
             else
             {
             {
-                action = x => method.Invoke(instance, new[] { x });
+                action = x =>
+                {
+                    object result = method.Invoke(instance, new[] { x });
+                    if (result is Task task)
+                        task.ContinueWith(ActionOnException, TaskContinuationOptions.OnlyOnFaulted);
+                };
             }
             }
 
 
             string name = attribute.InternalName;
             string name = attribute.InternalName;

+ 2 - 2
src/PixiEditor/ViewModels/SubViewModels/Main/MiscViewModel.cs

@@ -20,7 +20,7 @@ internal class MiscViewModel : SubViewModel<ViewModelMain>
     [Command.Basic("PixiEditor.Links.OpenRepository", "https://github.com/PixiEditor/PixiEditor", "Repository", "Open Repository", IconPath = "Globe.png")]
     [Command.Basic("PixiEditor.Links.OpenRepository", "https://github.com/PixiEditor/PixiEditor", "Repository", "Open Repository", IconPath = "Globe.png")]
     [Command.Basic("PixiEditor.Links.OpenLicense", "https://github.com/PixiEditor/PixiEditor/blob/master/LICENSE", "License", "Open License", IconPath = "Globe.png")]
     [Command.Basic("PixiEditor.Links.OpenLicense", "https://github.com/PixiEditor/PixiEditor/blob/master/LICENSE", "License", "Open License", IconPath = "Globe.png")]
     [Command.Basic("PixiEditor.Links.OpenOtherLicenses", "https://pixieditor.net/docs/Third-party-licenses", "Third Party Licenses", "Open Third Party Licenses", IconPath = "Globe.png")]
     [Command.Basic("PixiEditor.Links.OpenOtherLicenses", "https://pixieditor.net/docs/Third-party-licenses", "Third Party Licenses", "Open Third Party Licenses", IconPath = "Globe.png")]
-    public static void OpenHyperlink(string url)
+    public static async Task OpenHyperlink(string url)
     {
     {
         try
         try
         {
         {
@@ -29,7 +29,7 @@ internal class MiscViewModel : SubViewModel<ViewModelMain>
         catch (Exception e)
         catch (Exception e)
         {
         {
             NoticeDialog.Show(title: "Error", message: $"Couldn't open the address {url} in your default browser");
             NoticeDialog.Show(title: "Error", message: $"Couldn't open the address {url} in your default browser");
-            _ = CrashHelper.SendExceptionInfoToWebhook(e);
+            await CrashHelper.SendExceptionInfoToWebhook(e).Wait();
         }
         }
     }
     }
 }
 }