如何处理AppDomain.Unload和相关的ThreadAbortException

时间:2012-02-23 15:31:55

标签: c# .net appdomain threadabortexception

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

  

域中的线程使用Abort方法终止,该方法   在线程中抛出ThreadAbortException。虽然线程   应该立即终止,它可以继续执行   finally子句中不可预测的时间量。 - 来自MSDN

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

实际上这实际上是elimates catch(Exception ex)因为它会捕获ThreadAbortException并尝试处理它,通常是通过记录一个真的不应该记录的错误(因为卸载AppDomain不是'真的是一个例外)。

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

2 个答案:

答案 0 :(得分:5)

你几乎可以随时了解TAE的可能性。我唯一要做的就是你的代码应该已经用这种方式编写了 - 在处理具有可靠性要求的数据时,你应该在硬件故障,操作错误,OOM等情况下使用事务或其他补偿机制。 - 其中任何一个都不是AppDomain关闭方案所特有的。

最后,您应该知道可以捕获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等事务留给微软和Oracle的聪明人都在编写数据库。例如,如果您的代码正在执行平面文件I / O,您需要确定永远不会使文件处于错误状态,那么您应该以非常全面的方式考虑故障模式 - 喜欢"当这个文件被半写时电源消失会发生什么?"

1 唯一的例外是StackOverflow exceptions generally cannot be caught。这是.NET 2.0的一个变化。

答案 1 :(得分:1)

您无法处理ThreadAbortException因此无需捕获异常。更具技术性

  

是一个特殊的例外,可以被捕获,但会自动捕获   在追踪区块的最后再次被提升

来自here