c#, MAF,未处理异常管理在单独的AppDomain

本文关键字:单独 AppDomain 异常 MAF 未处理 管理 | 更新日期: 2023-09-27 18:12:27

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

问题是,我需要能够在子appdomain中获取未处理的异常,捕获它,然后让该appdomain优雅地失败,而不需要关闭父appdomain

我该怎么做呢?这似乎是一个微不足道的任务,使用独立的应用域的主要好处之一…

c#, MAF,未处理异常管理在单独的AppDomain

我想我对这个类似问题的回答应该对你有所帮助:

当其他域抛出异常时应用程序崩溃

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

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

再一次,据我所知,有两种方法来处理这个问题:

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

注意这两个是互补的。你可以从2开始。然后在不同的进程中加载不稳定的插件

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

下面的博客帖子帮助很大: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);
    }
}