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

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

我正在尝试处理两种types的exception:

  1. 在前台(UI)线程
  2. 在后台(线程池)线程

在全局处理程序的两种情况下,我想:

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

经过一定的调查后,我在 这里和这里find了一些答案,但除了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; }; 

然后在按钮单击时,我添加了以下代码以引发两种types的exception:

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

因此,我对两种types的exception都有不同的行为:

  1. 前景:
    • 两个处理程序都被提升了
    • 不可能阻止app崩溃 – 它会以任何方式崩溃(e.Handled = true只是被忽略)
  2. 背景:
    • 只引发第二个处理程序
    • 应用程序不会崩溃

在我的情况下,我无法在try-catch中包装每个用户操作,尤其是后台任务。 我有业务登录,如果出现错误应该被中断,这正是我对运行时的期望。 同时我想在一个地方的顶层处理这些exception,记录它们(根据我的业务规则)并继续执行应用程序。

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

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

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

这些事件处理程序并非旨在让您exception中恢复 ,它们是最后的手段,可以让您在应用程序终止之前执行类似写入错误日志的操作。

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

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

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

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

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

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

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