如何全局处理MonoDroid未捕获的异常并防止应用程序崩溃

时间:2013-10-22 01:17:10

标签: android exception-handling xamarin.android xamarin unhandled-exception

我正在尝试在我的monodroid应用程序中实现有效的异常处理,该应用程序是用Visual Studio的Xamarin.Android插件编写的。

我正在尝试处理两种类型的例外:

  1. at foreground(UI)thread
  2. at background(threadpool)thread
  3. 在全局处理程序的两种情况下,我都想:

    • 记录 - (提交分析事件)
    • 用户通知 - (提醒)

    经过一定的调查后,我发现了一些答案hereherehere,但除了AndroidEnvironment.UnhandledExceptionRaiser和AppDomain.UnhandledException之外什么都没有提出,并且它并不适用于所有情况。

    我创建了一个简短的示例,我试图使用这两个处理程序:

    AppDomain.CurrentDomain.UnhandledException += (s,e)=>
    {
        System.Diagnostics.Debug.WriteLine("AppDomain.CurrentDomain.UnhandledException: {0}. IsTerminating: {1}", e.ExceptionObject, e.IsTerminating);
    };
    
    AndroidEnvironment.UnhandledExceptionRaiser += (s, e) =>
    {
        System.Diagnostics.Debug.WriteLine("AndroidEnvironment.UnhandledExceptionRaiser: {0}. IsTerminating: {1}", e.Exception, e.Handled);
        e.Handled = true;
    };
    

    然后点击按钮我添加了以下代码以引发两种类型的异常:

    //foreground exception
    throw new NullReferenceException("test nre from ui thread.");
    //background exception
    ThreadPool.QueueUserWorkItem(unused =>
    {
        throw new NullReferenceException("test nre from back thread.");
    });
    

    因此,我对两种类型的例外都有不同的行为:

    1. 前景:
      • 两个处理程序都被提升
      • 不可能阻止应用程序出现 崩溃 - 它将以任何方式崩溃(e.Handled = true只是被忽略)
    2. 背景:
      • 仅引发第二个处理程序
      • app不会崩溃
    3. 在我的情况下,我无法在try-catch中包装每个用户操作,尤其是后台任务。 我有业务登录,如果出现错误应该被中断,这正是我对运行时的期望。同时我想在一个地方的顶层处理这些异常,记录它们(根据我的业务规则)并继续执行应用程序。

      如何处理这两个异常并且仍然​​能够使应用程序保持活动状态(防止崩溃)。

      您可以在此处找到完整的代码示例: https://dl.dropboxusercontent.com/u/19503836/UnhandledException.zip

      感谢您的建议。任何帮助赞赏。 TIA!

2 个答案:

答案 0 :(得分:8)

这些事件处理程序并非旨在让您中恢复异常,它们是让您有机会在应用程序终止之前写入错误日志的最后手段

您已经提到要记录错误 - 这应该可以正常工作,但可能无法向用户显示错误,因为您的应用程序已经达到了甚至无法执行此操作的程度。

正如您对问题的评论所提到的,处理这样的异常是一个坏主意。

虽然您可能对何时调用此函数有非常具体的期望,但您的应用程序可能会在任何时候抛出异常 - 无论出于何种原因。设计它是不可能的,以便正确处理所有

即使您可以安全地编写一些内容来处理任何异常,您的应用仍将因未处理的异常而终止。

AppDomain.CurrentDomain.UnhandledException的Microsoft文档提供了有关此内容的更多信息:

http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx

答案 1 :(得分:2)

@ Daveoc64 - 我不同意你(以及其他人)强调全局处理未捕获的异常是一个坏主意 - 我认为它是UI应用程序的必需品。它并没有否定方法级别的正确异常处理(即,您可以处理并从特定异常中恢复,其中上下文在您强调时非常重要) - 但除此之外还使用它,有时候,当发生异常时,该应用程序无法恢复。因此,在代码中添加一个try / catch来捕获一个无法恢复的异常是没有意义的 - 就像你放在catch块中一样 - 你必须复制并放入所有其他catch块以获得相同类型的不可恢复的错误 - 即向用户显示提示并正常退出..为什么在整个代码库中一遍又一遍地重复那种处理 - 它是一种非常简单的 - 一种全局异常处理程序,以满足这种关注更有意义!

相关问题