通常是的,最终将运行。
对于以下三种情况,最终将始终运行:
- 没有例外发生
- 同步异常(正常程序流中发生的异常)。
这包括从System.Exception派生的符合CLS的异常和不从System.Exception派生的不符合CLS的异常。不符合CLS的异常由RuntimeWrappedException自动包装。C#不能引发非CLS投诉异常,但是C ++这样的语言可以。C#可能会调用以可能引发不符合CLS规范的异常的语言编写的代码。
- 异步ThreadAbortException
从.NET 2.0开始,ThreadAbortException将不再阻止finally运行。现在将ThreadAbortException提升到finally之前或之后。只要在线程中止发生之前实际输入了try,finally就会一直运行,并且不会被线程中止中断。
在以下情况下,最终将无法运行:
异步StackOverflowException。
从.NET 2.0开始,堆栈溢出将导致进程终止。除非应用了进一步的约束以使最终CER(受约束执行区域)生效,否则最终将不会运行。CER不应在一般用户代码中使用。仅应在始终运行清除代码的关键位置使用它们-无论如何,在所有进程都因堆栈溢出而关闭后,默认情况下将清除所有托管对象。因此,CER唯一相关的地方是在流程之外分配的资源,例如非托管句柄。
通常,非托管代码在被用户代码使用之前被某些托管类包装。托管包装器类通常将使用SafeHandle包装非托管句柄。SafeHandle实现了一个关键的终结器,以及一个在CER中运行的Release方法,以确保执行清理代码。因此,您不应看到CER在整个用户代码中乱七八糟。
因此,最终不会在StackOverflowException上运行的事实对用户代码没有任何影响,因为该过程无论如何都会终止。如果在某些情况下确实需要清除SafeHandle或CriticalFinalizerObject之外的某些非托管资源,请按以下方式使用CER;但是请注意,这是一种不好的做法-非托管概念应通过设计抽象为托管类和适当的SafeHandle。
例如,
// No code can appear after this line, before the try
RuntimeHelpers.PrepareConstrainedRegions();
try
{
// This is *NOT* a CER
}
finally
{
// This is a CER; guaranteed to run, if the try was entered,
// even if a StackOverflowException occurs.
}