17

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

我正在尝试处理两种类型的异常:

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

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

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

经过一定的调查后,我在此处此处此处找到了一些答案,但除了 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. 背景:
    • 仅引发第二个处理程序
    • 应用程序不会崩溃

就我而言,我无法将每个用户操作都包含在 try-catch 中,尤其是后台任务。我有业务登录,如果出现错误应该中断,这正是我对运行时的期望。同时,我想在一个地方处理顶级异常,记录它们(基于我的业务规则)并继续执行应用程序。

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

You can find complete code sample here: https://dl.dropboxusercontent.com/u/19503836/UnhandledException.zip

Thank you for your advice. Any help appreciated. TIA!

4

2 回答 2

9

These event handlers aren't designed to let you recover from the exception, they're a last resort to give you an opportunity to do something like writing to an error log before the application is terminated.

You've mentioned that you want to log errors - that should work fine, but displaying an error to the user might not be possible because your Application will have reached a point where it is not even able to do that.

As the comment on your question mentions, it is a bad idea to handle exceptions like this.

While you might have a very specific expectation of when this is going to be called, your App could throw an exception at any point - and for any reason. It's impossible to design it so that it handles everything correctly.

Even if you could write something to deal with any exception safely, your App will still be terminated because of the unhandled exception.

The Microsoft documentation for AppDomain.CurrentDomain.UnhandledException gives some more information on this:

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

于 2013-10-22T10:35:12.463 回答
3

@Daveoc64 - I disagree with you (and others) that have stressed that global handling of uncaught exceptions is a bad idea - i'd say its a necessity for UI applications. It doesn't negate proper exception handling at the method level (i.e where you can handle and recover from specific exceptions in which context is very important as you stressed) - but it's used in addition to it, as sometimes, when an exception occurs, there is no recovery for the application. Therefore putting a try / catch in code to catch an exception that you cannot recover from is pointless - as whatever you put inside that catch block - you'd have to copy and put inside all other catch blocks for the same sort of unrecoverable errors - i.e display a prompt to the user and gracefully exit.. Why repeat that sort of handling throughout the entire code base over and over again - its rediculous - a global exception handler to cater for that kind of concern makes much more sense!

于 2015-06-30T14:12:42.707 回答