11 回答
您可以将事件处理程序添加到 AppDomain.UnhandledException 事件,当异常被抛出但未被捕获时,它将被调用。
与其他人发布的内容相反,捕获所有异常并没有错。重要的是要妥善处理它们。如果您有堆栈溢出或内存不足的情况,应用程序应该为它们关闭。另外,请记住,OOM 条件可能会阻止您的异常处理程序正确运行。例如,如果您的异常处理程序显示一个带有异常消息的对话框,如果您的内存不足,则可能没有足够的空间用于对话框显示。最好记录下来并立即关闭。
正如其他人所提到的,您可以处理 UnhandledException 和 ThreadException 事件来收集可能会错过的异常。然后只需在主循环周围抛出一个异常处理程序(假设是一个 winforms 应用程序)。
此外,您应该知道 OutOfMemoryExceptions 并不总是因内存不足而引发。OOM 条件可以在您的代码或框架中触发各种异常,这些异常不一定与真正的底层条件内存不足这一事实有关。当根本原因实际上是内存不足时,我经常看到 InvalidOperationException 或 ArgumentException。
我们的主持人 Jeff Atwood 在 codeproject 中的这篇文章 正是您所需要的。包括捕获未处理异常的代码和向用户显示有关崩溃信息的最佳实践。
Global.asax类是您的最后一道防线。看着:
protected void Application_Error(Object sender, EventArgs e)
方法
请注意,某些异常很容易被捕获 - 或者大部分是无法捕获的,
- OutOfMemoryException:您在 catch 处理程序中执行的任何操作都可能分配内存(在 CLR 的托管或非托管端)并因此触发另一个 OOM
- StackOverflowException:取决于 CLR 是否足够早地检测到它,您可能会收到通知。最坏的情况是,它只会终止进程。
您可以使用 AppDomain.CurrentDomain.UnhandledException 来获取事件。
尽管在没有计划正确处理它们的情况下捕获所有异常肯定是一种不好的做法,但我认为应用程序应该以某种优雅的方式失败。崩溃不应该把用户吓死,至少它应该显示错误的描述,向技术支持人员报告的一些信息,理想情况下是一个关闭应用程序并重新启动它的按钮。在理想情况下,应用程序应该能够将用户数据转储到磁盘上,然后尝试恢复它(但我发现这要求太多了)。
无论如何,我通常使用:
AppDomain.CurrentDomain.UnhandledException
您也可以使用 Application.ThreadException 事件。
曾经我正在开发一个在基于 COM 的应用程序中运行的 .NET 应用程序;这个事件非常有用,因为 AppDomain.CurrentDomain.UnhandledException 在这种情况下不起作用。
请注意,捕获这些未处理的异常可能会改变应用程序的安全要求。您的应用程序可能会在某些情况下停止正常运行(从网络共享运行时等)。一定要彻底测试。
同时使用 AppDomain.CurrentDomain.UnhandledException Application.ThreadException 并没有什么坏处
但请记住,辅助线程上的异常不会被这些处理程序捕获;如果需要,将SafeThread用于辅助线程