Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 为什么子AppDomain中的StackOverflowException终止父AppDomain?_.net_Appdomain_Stack Overflow - Fatal编程技术网

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

.net 为什么子AppDomain中的StackOverflowException终止父AppDomain?,.net,appdomain,stack-overflow,.net,Appdomain,Stack Overflow,我的印象是AppDomains是相互隔离的。似乎在StackOverException的情况下,情况并非如此 为了演示这个问题,我创建了一个简单的控制台应用程序,其唯一目的是生成一个新的AppDomain,在其中加载一个非常简单的程序集并调用其中的一个方法。此方法碰巧抛出StackOverflowException。这会导致控制台应用程序意外终止 我期望的行为是“子”AppDomain在出现这种异常时崩溃并烧掉,但让我的控制台应用程序在“父”AppDomain中运行,不会受到影响 这可能吗 更新

我的印象是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();
        }
    }

我假设问题是,您调用的方法导致了主AppDomain中的异常,即您调用了主AppDomain中的某个方法,此方法从子AppDomain调用问题方法。异常在子AppDomain中出现,但会在调用堆栈中向上传播到调用AppDomain(主AppDomain)中。尝试完全从子AppDomain调用此方法。例如,在子AppDomain中生成一个线程,以便该线程调用problem方法。

只有托管内存在AppDomain之间被隔离。如果线程在任何AppDomain中引发异常,这将导致整个应用程序崩溃

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

但是,存在一种黑客行为,包括在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用户代码无法处理此异常。(见第页的备注部分)


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

有可能看到代码示例吗?:)我在过去也设置了类似的东西,可以抵御异常(尽管我不记得尝试过StackOverflowException)。我很想知道是否有什么奇怪的事情导致程序集被加载到默认的appdomain中。干杯生成线程将“隐藏”异常,即使您没有使用单独的appdomains。这不是必需的。您可以正确处理该线程内的异常。@DmitryLobanov告诉我们如何处理?谢谢您的回复。我在上面的问题中添加了一些代码,但我没有看到任何异常处理程序被命中,因此我不确定如何“正确”处理它们……启用legaceUnhandledExceptionPolicy是非常不明智的,因为这就像说“嘿,我不知道发生了什么,也不知道如何修复,停止抛出这个该死的异常”。它就像一个空的“抓住一切”块。我认为这种可能性是为了与遗留代码兼容,而不打算与新代码一起使用。