1

据我所知,当发生第一次机会异常时,会通知调试器(如果有),然后如果仍未处理,系统会在堆栈中搜索最近的基于帧的异常处理程序(如果有)。

当我了解向量异常处理时,我正在阅读此链接。

问题1)我想知道我们是否可以在托管代码中做到这一点?

问题2)我认为 anytry{}catch{}是基于帧的处理程序,但是当我们在某些事件上注册句柄时会发生什么,例如

AppDomain.CurrentDomain.UnhandledException += (x, y) =>
{
    Console.WriteLine("Unhandled exception");
};

这些是什么?

4

1 回答 1

1

只有附加了异常时,调试器才会收到通知。例如,如果您在 Visal Studio 中进行调试,则会首先调用它,如果它传递异常,则会调用异常处理程序。要让调试器在所有异常上停止,请从 Visual Studio 中选择“调试”菜单并选择“异常”,然后选择您希望调试器停止的异常。如果没有这些处理程序(或没有处理程序),则将第二次调用调试器以停止执行并显示发生异常的一般消息。另一方面,如果未附加调试器,则不会通知调试器——99% 以上的托管生产代码都是这种情况。

向量异常处理是一个低级 API,旨在从非托管代码(即 C++)中使用。托管代码 (C#) 的第一选择应该是使用带有 try/catch/finally 块的结构化异常处理。大多数 (99%+) 使用像 C# 这样的语言的托管代码开发人员,包括我自己,都发现结构化异常处理已经足够了。

如果您仍然认为需要使用此 api,则必须使用 P/Invoke 调用 AddVectoredExceptionHandler,这是从托管代码调用非托管代码的一种方式。有几点需要注意。有关一般概述,请参阅此链接。 Mike Stall 的博客建议避免托管代码中的向量异常。在这个线程中,Mike Stall 说非托管向量异常处理程序永远不应该回调到托管代码中。他还建议托管异常是向量异常处理中未记录的特性,MS 可能会在未来的 CLR 版本中消除该支持,因此使用风险自负。

AppDomain.UnhandledException 事件仅在没有找到其他处理程序时调用。它可以用于需要记录有关未处理异常的一些信息的情况,但是没有时间对大量现有代码进行适当的结构化异常处理,或者您可能无权访问代码那就是抛出异常。否则,应该使用 try/catch/finally 块。

您也可以尝试查看AppDomain.FirstChanceException 事件,这发生在调用第一个异常处理程序之前。如果您想要做的只是记录一些信息,以记录在其他人的代码中抛出的某些您无权处理的异常的信息,那么这个可能会很有用。它只是一个通知,而不是一个异常处理程序。我以前从未使用过它,所以不知道它对性能有多大影响。我在这里担心的是,Microsoft 开发人员有时会在 CLR 中抛出除真正错误之外的各种异常。要查看实际情况,请尝试将调试器设置为在每个异常上中断,包括 CLR 运行时异常。这可以在 Visual Studio 中从 Debug 菜单并选择 Exceptions 完成。因此,我不知道它会对性能产生多大影响,因为所有 CLR 异常也可能会引发此事件。公平地说,我最后一次这样做是在 VS 2008 上。这可能不是真的,或者对于更高版本的 CLR 来说不是真的。我也看不到限制此事件将触发的异常的方法。因此,您需要过滤掉您不感兴趣的异常并进行试验以评估其对性能的影响。

于 2014-06-14T01:02:34.497 回答