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

时间:2013-05-07 22:42:28

标签: c# .net exception appdomain maf

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

问题是,我需要能够在子appdomain中捕获未处理的异常,捕获它,然后让appdomain正常失败而不删除父appdomain

我该怎么做呢?这似乎是一项微不足道的任务,也是使用隔离appdomains的主要好处之一......

3 个答案:

答案 0 :(得分:1)

据我所知,你不能开箱即用。您可以对外接程序视图使用抽象类,并在任何地方添加try / catch块以及模板方法模式(即抽象外接程序视图中的Read方法调用外接程序应实现的虚拟ReadCore函数)。仍然无法处理从子AppDomain的子线程抛出的未处理异常。这些会使您的应用崩溃。

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

  1. 使用进程隔离。这是确保加载项不会使主机崩溃的唯一方法。
  2. 按照System.AddIn小组博客中Using AppDomain Isolation to Detect Add-In Failures文章中介绍的方法进行操作。这种方法无法阻止您的应用程序崩溃,但您的应用程序将知道哪个加载项导致崩溃。这是有价值的信息,因为您的应用程序可以禁用不稳定的加载项,并避免在下次启动时加载它们。或者应用程序可以通知用户并让他/她决定该做什么。
  3. 请注意,这两者是互补的。您可以从2.开始,然后在不同的进程上加载不稳定的加载项。

答案 1 :(得分:1)

我认为我对这个类似问题的回答可以帮到你:

Application crash when anoter domain throws exception

如果您需要更多信息,请与我们联系。

答案 2 :(得分:0)

今天看起来效果很好的方法很糟糕,但在我发现这种方法的后果之前我还有一些需要做的事情......

以下博客文章帮助极大: http://ikickandibite.blogspot.com/2010/04/appdomains-and-true-isolation.html

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

(作为一个仅供参考,即使在我关注的.Net 4.5中仍然可用)

<?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>

...从那时起,我可以使用AppDomain.UnhandledException事件来拦截未处理的异常并卸载子域...(注意我在这里松散地说'拦截'......我还没有'捕捉'异常,只记下它在过程中卸载插件)

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);
    }
}