11

我正在尝试在我的monodroid应用程序中使用Xamarin.Android插件为Visual Studio编写有效的异常处理。如何在全球范围内处理MonoDroid未捕获的异常并防止应用程序崩溃

我试图处理2种异常:

  1. 在前台(UI)线程
  2. 在背景(线程池)螺纹

在这两种情况下,在全球处理器I” m想要:

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

一定的调查后,我已经找到了一些答案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. 背景:
    • 只有第二处理程序提出
    • 应用程序不会崩溃

在我的情况下,我无法在try-catch中包装每个用户动作,尤其是后台任务。 我有企业登录,应该在错误的情况下中断,这正是我期望从运行时。同时,我想在一个地方处理顶层的异常情况,记录它们(基于我们的业务规则)并继续执行应用程序。

如何处理这两个异常,并仍然有能力保持应用程序活着(防止崩溃)。

你可以在这里找到完整的代码示例: https://dl.dropboxusercontent.com/u/19503836/UnhandledException.zip

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

+6

这种方法异常处理是设计非常差。例外情况应该在提出和预期的地方处理,而不是在全球范围内处理。一旦异常冒泡到全局处理程序,就会失去所有上下文和恢复状态的所有希望。 – 323go

+1

谢谢您的意见,但我不能同意。我很明白,我同意在丢失背景之前处理异常,但我不同意在他们提出异议的情况下处理异常。成像我有DataAccess,业务逻辑和用户界面,我有UI级别的按钮启动一些数据访问操作,然后由业务逻辑处理,最终结果显示在UI上。如果在数据访问级别发生任何错误,我希望我的数据访问和业务逻辑被中断,并在UI级别显示结果。例外的是设计不是每一个方法调用之后检查错误... –

+0

我同意,我希望我应该处理这个错误 - 在UI层面,而不是它被提出(在数据访问层)。在我的问题中,我正在讨论UI级别错误处理的一般方法(对UI错误处理程序无法记录错误进行映像)。在这种情况下,我仍然希望我的应用程序通知用户它,记录此后续错误,并让我的应用程序不会崩溃(在我的情况下,记录错误的失败不是一个关键问题)。我想要的是决定我的自我,如果应用程序应该被终止,当引发异常的异常时。 –

回答

7

这些事件处理程序不是为了让你从异常中恢复,他们是不得已给你一个机会做类似的应用程序被终止之前写入错误日志。

你提到要记录错误 - 应该做工精细,但显示错误的用户可能不是可能的,因为你的应用程序将达到世界地步,甚至没有能够做到这一点。

随着对你的问题的评论中提到,这是一个坏主意来处理这样的例外。

虽然你可能在这个将被称为一个非常具体的期望,你的应用程序可以扔在任何时候例外 - 以任何理由。设计它是不可能的,所以它正确处理的一切

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

为AppDomain.CurrentDomain.UnhandledException微软文档提供了一些这方面的更多信息:

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

+0

谢谢,你是绝对正确的,没有人能保证他的错误处理逻辑能够处理所有事情,但我确实希望保证这些关键的情况将被记录下来并且用户将被通知(即使在应用崩溃之前,但仍然没有静音崩溃) 。 –

+1

实现这两种方法应该让你做你想要的日志记录(我已经在我的Xamarin.Android应用程序中使用过),但是你几乎肯定会发现任何一种UI - AlertDialog,Toast或者一个新的Activity都不能一旦App达到这个状态就会显示。 – Daveoc64

+1

这是我关心的问题。谢谢你的细节。所以在关键情况下,无声的崩溃是Android的方式来通知用户有关严重错误:(例如,在Windows Phone中,您可以在收到非原因错误时记录,通知并和平终止进程。 –

1

@ Daveoc64 - 我与你(及其他)不同意,都强调捕获的异常的全球处理是一个坏主意 - 我会说它是UI应用程序的必要条件。它并不否定适当的方法级别的异常处理(也就是说,您可以在特定的异常情况下处理和恢复上下文非常重要的异常),但是除了它之外,还会使用异常处理,有时候会发生异常,应用程序没有恢复。因此,把一个try/catch代码赶上,你不能从恢复的例外是毫无意义的 - 因为无论你把catch块 - 你必须复制,并把所有其他catch块内对同一类型的不可恢复错误 - 即向用户显示提示并优雅地退出。为什么在整个代码库中一遍又一遍地重复这种处理 - 它的复杂性 - 一个全局的异常处理程序来迎合这种担心会更有意义!

+1

如前所述,当意外的异常发生时,您根本无法控制。并且你的程序也不可能知道,任何试图从错误中恢复的尝试都是徒劳的,并且可能是危险的,因为它可能会导致你的应用程序不正确地运行并导致dat亏损。 – Daveoc64

+0

@ Daveoc64 - 我不是在谈论试图恢复..正如我上面写的,我正在谈论一个优雅的退出程序。也许这意味着试图将异常细节写入您选择的记录器,向用户显示“悲伤的脸”笑脸,并通知他们程序必须退出。 – Darrell

+1

同样,我们已经注意到,几乎在所有情况下都可以将异常详细信息写入日志记录机制,但Android的实际情况是,当应用程序崩溃时,操作系统根本不会让您对UI执行任何操作。就它而言,你已经搞砸了一些东西,它有一种处理所有应用程序的方式 - 一个标准的操作系统对话框。如果您确实需要向用户显示自定义消息,请考虑将崩溃记录到您可以查询的地方,然后在下次启动应用时显示消息。 – Daveoc64

相关问题