2

根据 MSDN,AppDomain.Unload 会导致卸载 AppDomain 内的所有线程抛出线程中止异常。

域中的线程使用 Abort 方法终止,该方法在线程中引发 ThreadAbortException。尽管线程应该立即终止,但它可以在 finally 子句中继续执行不可预测的时间。-- 来自MSDN

所以我的理解是,每次我在任何地方编写预期在此 AppDomain 中运行的代码时,我都必须期望线程中止可能随时在任何线程上发生。这是真的?任何地方的所有代码都应该假设可以随时抛出 ThreadAbortException 吗?

实际上,这实际上消除了 catch(Exception ex)因为这将捕获 ThreadAbortException 并尝试处理它,通常通过记录一个确实不应该记录的错误(因为卸载 AppDomain 并不是真正的异常)。

是否需要考虑其他任何因素来避免不必要的异常处理/错误记录?

4

2 回答 2

5

您对 TAE 的可能性在任何时候都抱有正确的期望。我要说的唯一一点是,您的代码可能应该已经以这种方式编写了-在处理具有可靠性要求的数据时,您应该在硬件故障、操作员错误、OOM 等情况下使用事务或其他补偿机制-任何其中并非 AppDomain 关闭场景独有。

最后,您应该知道您可以在 catch 块中捕获 TAE 并执行补偿代码。它们唯一的特别之处是它们会在 catch 块之后立即被重新抛出,所以你不能“吞下”它们。您可以使用 来抑制它们Thread.ResetAbort(),但在这种情况下,这可能不是预期的效果。

我们都写过这样的代码:

public void Foo() {
    try {
        Do.Some.Stuff();
    } catch (Exception ex) {
       Console.Out.WriteLine("Oh noes!");
    }
}

是的,catch 块将捕获所有内容1,包括 TAE 和 OOM。

这里要记住的是,对于上述所有例外情况,世界基本上都在结束。您应该关心的是,您正在处理的任何事务敏感数据都不会丢失或处于不良状态,这就是为什么我们通常将事务安全 I/O 之类的事情留给 Microsoft 和 Oracle 的聪明人谁写数据库。例如,如果您的代码正在执行平面文件 I/O,您需要确保永远不会使文件处于错误状态,那么您应该以非常全面的方式考虑故障模式——比如“如果这个文件写到一半就断电了?”

1唯一的例外是StackOverflow 异常一般不能被捕获。这是 .NET 2.0 中的一个变化。

于 2012-02-23T15:36:22.800 回答
1

您无法处理ThreadAbortException,因此无需捕获异常。从技术上讲

是一个可以被捕获的特殊异常,但在catch块结束时会自动再次引发

这里

于 2012-02-23T15:35:22.213 回答