【问题标题】:How to try/catch all exceptions如何尝试/捕获所有异常
【发布时间】:2024-01-12 12:05:01
【问题描述】:

我正在完成由其他人启动的 UWP 应用。该应用程序经常崩溃,我总是在 App.g.i.cs

结束
if (global::System.Diagnostics.Debugger.IsAttached)
    global::System.Diagnostics.Debugger.Break(); 

然后我不得不说“不,不要启动调试器”并关闭 2 个窗口。

有没有什么地方我可以尝试/捕获,这样每次发生这种情况时我都不必重新启动应用程序?我在AppShellApp 中找不到任何内容。

或者我是否必须在每个事件处理程序中放置一个 try/catch?

【问题讨论】:

    标签: c# exception-handling uwp win-universal-app


    【解决方案1】:

    如果您想避免每次遇到未处理的异常时启动新的调试器并重新启动应用程序,您可以使用Application.UnhandledException event并将事件参数的Handled属性设置为true,如下所示:

    public App()
    {
        this.InitializeComponent();
        this.Suspending += OnSuspending;
        this.UnhandledException += (sender, e) =>
        {
            e.Handled = true;
            System.Diagnostics.Debug.WriteLine(e.Exception);
        };
    }
    

    UnhandledException 事件用于通知应用有关 XAML 框架或一般 Windows 运行时遇到的尚未由应用代码处理的异常。

    通常在触发 UnhandledException 事件后,Windows 运行时会终止应用程序,因为该异常未被处理。应用程序代码对此有一些控制:如果 UnhandledException 事件处理程序将事件参数的 Handled 属性设置为 true,那么在大多数情况下应用程序不会终止。

    更多信息,请参阅Application.UnhandledException event备注和博客:Strategies for Handling Errors in your Windows Store Apps

    【讨论】:

    • 非常感谢!听起来完全符合我的需要。
    • 这实际上并不能帮助您找到并修复您的错误……充其量只是一个临时的创可贴。
    【解决方案2】:

    据我所知,你不能做你想做的事(大的 try catch 块),出于所有意图和目的,你甚至不应该考虑这种可能性。

    首先尝试确定应用程序崩溃的原因,在哪个页面上,当您尝试特定的东西时,每次都是相同的东西,然后您可以尝试捕获该特定页面上的一些方法并确定导致崩溃的原因

    【讨论】:

    • 我在生产中完全同意你的观点,但是在开发期间,我正在解决许多问题,不得不在调试器启动后不断重启进程(至少在我的电脑上) ) 似乎比“常规”Windows 应用程序慢。感谢您的回复!
    • VS 调试器是一个缓慢的过程 xD 但实际上您无能为力。UWP 使用异步调用,因此没有 Start 方法可以尝试在执行期间捕获任何错误或异常:/试着了解它的来源。对不起,我可以提供更多帮助
    【解决方案3】:

    如果您想处理原因而不是症状,您应该在调试器设置中启用首次机会异常。然后调试器应该在异常源处中断,而不是在全局处理程序中。然后,您可以直接解决问题的根本原因。

    即使您不知道它失败的原因,发布具有全局处理程序的应用程序也会盲目地将每个异常设置为“已处理”,这并不是一个好的解决方案。

    【讨论】:

      【解决方案4】:

      您可以在主应用程序中尝试/捕获以捕获所有异常。显示的是使用 Xamarin Forms DisplayAlert 的示例:

                  try
                  {
                      //throw new Exception("gone and done it");
                      MyMainProgram();
                                      }
                  catch (Exception ex)
                  {
                      await DisplayAlert("Whoops!", ex.Message, "ok");
                      throw ex;
                  }
      

      您可以通过取消注释“抛出新异常”来测试这一点。执行会因您必须回答的警告而停止,然后通过抛出异常继续以防止执行损坏的代码。

      【讨论】:

      • 我个人永远不会重新抛出这样的异常。您将完全忘记堆栈跟踪。要么使用throw;,要么将其包装在一个新的异常中。