【问题标题】:How to handle MonoDroid uncaught exceptions globally and prevent application from crash如何全局处理 MonoDroid 未捕获的异常并防止应用程序崩溃
【发布时间】:2013-10-22 01:17:09
【问题描述】:

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

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

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

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

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

经过一定的调查,我找到了一些答案 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.");
});

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

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

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

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

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

感谢您的建议。任何帮助表示赞赏。 蒂亚!

【问题讨论】:

  • 这种异常处理方法的设计非常糟糕。应该在引发和预期的地方处理异常,而不是全局处理。一旦异常冒泡到全局处理程序,您就失去了所有上下文和恢复状态的所有希望。
  • 感谢您的意见,但我不能同意。我确实理解并且我同意我应该在它丢失上下文之前处理异常,但我不同意在他们提出的异常处处理。成像 我有数据访问、业务逻辑和 UI,我在 UI 级别有按钮,它启动一些数据访问操作,然后由业务逻辑处理,最后结果显示在 UI 上。如果数据访问级别发生任何错误,我希望我的数据访问和业务逻辑被中断,结果显示在 UI 级别。异常被设计为在每次方法调用后不检查错误...
  • 我同意我应该在我期望的地方处理这个错误 - 在 UI 级别,而不是在它引发的地方(在数据访问级别)。在我的问题中,我谈论的是在 UI 级别处理错误错误的一般方法(想象 UI 错误处理程序未能记录错误)。在这种情况下,我仍然希望我的应用程序通知用户,记录此后续错误并且让我的应用程序不崩溃(在我的情况下,未能记录错误不是关键问题)。我想要的是决定我自己是否应该在引发未经处理的异常时终止应用程序。
  • 正如我之前所说,一般情况不是恢复而是记录错误并通知用户 - 但不是静默的应用程序崩溃。无声崩溃 - 这是一个糟糕的架构设计。
  • @323go 我是 Android 开发新手,所以请帮助我了解替代方案:如何处理应用程序中的意外错误?您是否将每个用户操作(按钮单击事件处理程序等)包装在 try/catch 中,或者是否有另一种方法来执行“如果所有其他方法都失败,至少向用户显示异常消息?”

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


【解决方案1】:

@Daveoc64 - 我不同意你(和其他人)强调全局处理未捕获异常是一个坏主意 - 我会说它是 UI 应用程序的必要条件。它不会在方法级别否定正确的异常处理(即,您可以在其中处理和从特定异常中恢复,其中上下文非常重要,正如您所强调的那样) - 但它是除此之外使用的,有时,当异常发生时,应用程序无法恢复。因此,在代码中放入 try / catch 来捕获无法恢复的异常是没有意义的——就像你放在那个 catch 块中的任何东西一样——对于相同类型的不可恢复的错误,你必须复制并放入所有其他 catch 块中——即向用户显示提示并优雅地退出。为什么要在整个代码库中一遍又一遍地重复这种处理 - 这很荒谬 - 满足这种关注的全局异常处理程序更有意义!

【讨论】:

  • 如前所述,当发生意外异常时,您根本无法控制。你不知道发生了什么,你的程序也不可能知道。任何从错误中恢复的尝试充其量都是徒劳的并且存在潜在危险,因为它可能会导致您的应用程序行为不正确并导致数据丢失。
  • @Daveoc64 - 我不是在谈论尝试恢复。正如我在上面所写的,我在谈论一个优雅的退出过程。也许这意味着尝试将异常详细信息写入您选择的记录器,向用户显示“悲伤的脸”笑脸并道歉,通知他们程序必须退出。
  • 再次,已经注意到您几乎可以在所有情况下将异常详细信息写入日志记录机制,但 Android 的实际情况是操作系统根本不允许您对 UI 进行任何操作当应用程序崩溃时。就它而言,你搞砸了一些东西,它有一种方法可以处理所有应用程序 - 一个标准的操作系统对话框。如果您确实觉得需要向用户显示自定义消息,请考虑在您可以查询的地方记录崩溃,然后在他们下次启动您的应用时显示消息。
  • @Daveoc64 - 我更喜欢这个答案,即它是一个 android 限制,您无法在这种情况下显示 UI,我对那些仅仅想要这样做是“糟糕的设计”的建议做出反应 - 这更像是一个我不同意实施许多优雅的应用程序退出例程的观点!谢谢你的回答。
【解决方案2】:

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

您提到您想要记录错误 - 这应该可以正常工作,但可能无法向用户显示错误,因为您的应用程序将达到它甚至无法做到这一点的程度。

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

虽然您可能对何时调用它有一个非常具体的期望,但您的应用可能会在任何时候抛出异常 - 并且出于任何原因。不可能将其设计为正确处理一切。

即使您可以编写一些东西来安全地处理任何异常,您的应用仍然会因为未处理的异常而终止。

AppDomain.CurrentDomain.UnhandledException 的 Microsoft 文档提供了更多相关信息:

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

【讨论】:

  • 谢谢,你是绝对正确的,没有人能保证他的错误处理逻辑会处理所有事情,但我确实想保证会记录这些关键情况并通知用户(甚至在应用程序崩溃之前) ,但仍然没有无声崩溃)。
  • 实现这两种方法应该可以让你做你想要的日志记录(我在我的 Xamarin.Android 应用程序中使用过),但你几乎肯定会发现任何类型的 UI - AlertDialog、Toast或者一旦 App 达到此状态,新的 Activity 将无法显示。
  • 这是我的担心。谢谢你的详细信息。因此,在严重情况下静默崩溃是通知用户严重错误的 Android 方式 :( 。例如,在 Windows Phone 中,您可以在收到未处理的错误时记录、通知并和平终止进程。
  • @Daveo64 全局异常处理非常重要,以防在运行时发生您从未计划过的事情。我的 Windows Phone 应用程序从未崩溃过。他们为什么要这样做?我的所有应用程序都不会崩溃,而是向用户显示有关错误的通知,然后询问用户是否要关闭应用程序或继续使用它。请告诉我,这还不够礼貌吗? Android 让我感到恶心,因为我找不到相同的解决方案。
猜你喜欢
  • 2018-06-14
  • 1970-01-01
  • 2013-10-25
  • 1970-01-01
  • 1970-01-01
  • 2021-11-19
  • 1970-01-01
  • 2013-04-06
  • 1970-01-01
相关资源
最近更新 更多