.net - 为什么子 AppDomain 中的 StackOverflowException 会终止父 AppDomain?

标签 .net appdomain stack-overflow

我的印象是 AppDomains 彼此隔离。似乎在 StackOverException 的情况下,情况并非如此。

为了演示这个问题,我创建了一个简单的控制台应用程序,其唯一目的是生成一个新的 AppDomain,我将一个非常简单的程序集加载到其中并调用其中的一个方法。此方法碰巧抛出 StackOverflowException。这会导致我的控制台应用程序毫不客气地终止。

我想要的行为是让“子”AppDomain 在此类异常时崩溃并烧毁,但让我的控制台应用程序在“父”AppDomain 中运行,毫发无损。

这可能吗?

更新:这是一些代码。两个异常处理程序都没有被命中。

    class Program
    {
        static void Main(string[] args)
        {
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

            // create app domain
            var domain = AppDomain.CreateDomain("MyDomain");

            // create a component
            var component = (MyComponent)domain.CreateInstanceAndUnwrap(
                "AppDomainMonitor.Component", 
                typeof(MyComponent).FullName);

            // create a thread from a method on this component
            var thread = new Thread(component.CauseStackOverflow);

            // start the thread
            thread.Start();

            Console.ReadKey();
        }

        static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            // never hit
        }
    }

    public class MyComponent : MarshalByRefObject
    {
        public void CauseStackOverflow()
        {
            try
            {
                Infinite();
            }
            catch (Exception ex)
            {
                // never hit
            }
        }


        void Infinite()
        {
            Infinite();
        }
    }

最佳答案

AppDomains 之间仅隔离托管内存。如果一个线程在任何 AppDomain 中抛出异常,这将导致整个应用程序崩溃。

我认为最好的解决方案是确保在每个线程(或线程池工作项)上正确处理所有异常。

然而,有一个 hack 包括在 App.Config 文件中应用此配置:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
    <legacyUnhandledExceptionPolicy enabled="1"/>
  </runtime>
</configuration>

自 .Net 2.0 以来,未处理的异常使进程崩溃,但您可以使用此技巧恢复到旧策略。

我会谨慎地使用它,因为通常最好让进程崩溃而不是静默失败。您可以在 AppDomain.UnhandledException 中添加跟踪,以便在发生未处理的异常时得到通知并进行适当的处​​理。

编辑

你对 StackOveflowException 是正确的,因为 .Net 2.0 这个异常不能由用户代码处理。 (请参阅 this page in msdn 的备注部分)。

有一种方法可以通过创建自定义 CLR 主机来覆盖它,但这似乎是一件疯狂的事情。我想你必须忍受它,或者如果你真的需要这种容错,你可以创建子进程而不是 AppDomain。

关于.net - 为什么子 AppDomain 中的 StackOverflowException 会终止父 AppDomain?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5078209/

相关文章:

c# - 在 C# 中搜索子目录

c# - 使用 MarshalByRefObject 的 [Serializable] 属性或子类化?

java - 回合制游戏的游戏循环

c# - 如何在 .net 中的另一台计算机上运行进程

clojure - 如何以堆栈友好的方式反转和连接该映射?

c++ - SEH StackOverflow 异常 - 真的无法捕获吗?

c# - Outlook like 侧边栏并在 Outlook 中显示

c# - 直接将数据访问层的值接受到数据合约中是否正确?

.net - Silverlight 4 WCF 或 RIA 服务

asp.net - 如何在 ASP .NET 中动态插入网页(并更新插件)?