C#,MAF,在单独的AppDomain中进行未处理的异常管理

C#,MAF,在单独的AppDomain中进行未处理的异常管理,c#,.net,exception,appdomain,maf,C#,.net,Exception,Appdomain,Maf,好的,我有一个MAF应用程序,它在一个单独的appdomain中加载每个加载项。这对于我所需要的非常有用,因为它允许我在运行时动态卸载和重新加载我的加载项 问题是,我需要能够在子appdomain中接受未处理的异常,捕获它,然后让该appdomain在不关闭父appdomain的情况下正常地失败 我该怎么做呢?这似乎是一项琐碎的任务,也是使用独立appdomains的主要好处之一……据我所知,您不能开箱即用。您可以将抽象类用于外接程序视图,并将try/catch块与模板方法模式结合使用(即,抽象

好的,我有一个MAF应用程序,它在一个单独的appdomain中加载每个加载项。这对于我所需要的非常有用,因为它允许我在运行时动态卸载和重新加载我的加载项

问题是,我需要能够在子appdomain中接受未处理的异常,捕获它,然后让该appdomain在不关闭父appdomain的情况下正常地失败


我该怎么做呢?这似乎是一项琐碎的任务,也是使用独立appdomains的主要好处之一……

据我所知,您不能开箱即用。您可以将抽象类用于外接程序视图,并将try/catch块与模板方法模式结合使用(即,抽象外接程序视图中的Read方法调用外接程序应实现的虚拟ReadCore函数)。仍然无法处理从子AppDomain的子线程引发的未处理异常。这些将使你的应用程序崩溃

就我所知,有两种方法可以解决这个问题:

  • 使用进程隔离。这是确保加载项不会使主机崩溃的唯一方法
  • 遵循
    System.AddIn
    团队博客文章中描述的方法。这种方法无法阻止你的应用程序崩溃,但你的应用程序将知道是哪个加载项导致了崩溃。这是有价值的信息,因为这样你的应用程序可以禁用不稳定的加载项,避免在下次启动时加载它们。或者,应用程序可以通知用户,让他/她决定做什么

  • 请注意,这两者是互补的。你可以从2开始。然后在不同的进程上加载不稳定的加载项。

    我想我对这个类似问题的回答应该会帮助您:


    如果您需要更多信息,请告诉我。

    最终采用了一种今天看来效果不错的方法,尽管在我发现这种方法的后果之前,我还有一些挖掘工作要做

    下面的博文帮了大忙:

    我只是在app.config中启用了遗留的未处理异常策略:

    (仅供参考,即使在我所关心的.Net 4.5中也仍然可用)

    
    
    …从这一点上,我可以使用AppDomain.UnhandledException事件截获未处理的异常并卸载子域…(注意,我在这里松散地说“截获”…我仍然没有“捕获”异常,只是在过程中卸载加载项)

    Collection tokens=AddInStore.FindAddIns(typeof(iaapplicationaddin)、pipelineStoreLocation、addInPath);
    foreach(代币中的AddInToken代币)
    {
    AppDomain域=AppDomain.CreateDomain(token.Name);
    domain.UnhandledException+=(发送方,参数)=>
    {
    AppDomain _domain=(AppDomain)发送方;
    AppDomain.Unload(_domain);
    };
    WriteLine(“初始化外接程序“{0}”,token.Name);
    IAddIn addin=令牌.激活(域);
    尝试
    {
    加载项初始化(此);
    }
    捕获(例外情况除外)
    {
    WriteLine(“初始化外接程序“{0}”时出现问题:{1}”,token.Name,ex.Message);
    }
    }
    
    MAF!=MEF??。。。听起来很有趣,我希望我可以使用MEF,但是缺少模块重新加载功能真糟糕=(@jamesthrley如果你在答案上击败了我,我会给你积分的哈哈
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <startup> 
          <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
      </startup>
        <runtime>
            <legacyUnhandledExceptionPolicy enabled="true"/>
        </runtime>
    </configuration>
    
    Collection<AddInToken> tokens = AddInStore.FindAddIns(typeof(IApplicationAddIn), pipelineStoreLocation, addInPath);
    
    foreach (AddInToken token in tokens)
    {
        AppDomain domain = AppDomain.CreateDomain(token.Name);
        domain.UnhandledException += (sender, args) =>
            {
                AppDomain _domain = (AppDomain) sender;
                AppDomain.Unload(_domain);
            };
        Console.WriteLine("Initializing add-in '{0}'", token.Name);
        IAddIn addin = token.Activate<IAddIn>(domain);
    
        try
        {
            addin.Initialize(this);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Problem initializing add-in '{0}': {1}", token.Name, ex.Message);
        }
    }