我正在尝试在我的monodroid应用程序中实现有效的异常处理,该应用程序是用Visual Studio的Xamarin.Android插件编写的。
我正在尝试处理两种类型的例外:
在全局处理程序的两种情况下,我都想:
经过一定的调查后,我发现了一些答案here,here和here,但除了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.");
});
因此,我对两种类型的例外都有不同的行为:
在我的情况下,我无法在try-catch中包装每个用户操作,尤其是后台任务。 我有业务登录,如果出现错误应该被中断,这正是我对运行时的期望。同时我想在一个地方的顶层处理这些异常,记录它们(根据我的业务规则)并继续执行应用程序。
如何处理这两个异常并且仍然能够使应用程序保持活动状态(防止崩溃)。
您可以在此处找到完整的代码示例: https://dl.dropboxusercontent.com/u/19503836/UnhandledException.zip
感谢您的建议。任何帮助赞赏。 TIA!
答案 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块以获得相同类型的不可恢复的错误 - 即向用户显示提示并正常退出..为什么在整个代码库中一遍又一遍地重复那种处理 - 它是一种非常简单的 - 一种全局异常处理程序,以满足这种关注更有意义!