在模块化表单应用程序中使用AppDomain.UnhandledException

时间:2011-04-25 16:35:50

标签: c# .net winforms module appdomain

我目前正在开发一个完全模块化的.NET应用程序,其中包括:

  1. 主机应用程序加载模块DDL。模块DDL具有可以多次打开的表单。
  2. 您可以卸载应用程序域。这将导致模块的所有打开形式都被关闭。
  3. 我想要做的是,当模块中发生未处理的异常时,应用程序应卸载该模块的DDL并阻止主机崩溃。

    我尝试使用AppDomain.UnhandledException事件,该事件在创建后立即为其分配了一个处理程序。 AppDomain如下:

            // Creates the ApplicationDomain
            this._applicationDomain = AppDomain.CreateDomain(this.AppDomainName);
            this._applicationDomain.UnhandledException += new UnhandledExceptionEventHandler(_applicationDomain_UnhandledException);
    

    问题是:从不调用处理程序。微软称here

      

    例如,假设一个线程在应用程序域“AD1”中启动,在应用程序域“AD2”中调用一个方法,并从那里调用应用程序域“AD3”中的方法,它会抛出异常。可以引发UnhandledException事件的第一个应用程序域是“AD1”。如果该应用程序域不是默认应用程序域,则也可以在默认应用程序域中引发该事件。

    即使我分配了处理程序,异常仍然会转到

    Application.Run(new HostForm());

    我想,如果我为每个模块的表单创建了一个新的消息循环,它就可以工作,因为那个表单运行的线程将是一个独立的线程,但它似乎是一个愚蠢的解决方案。

    我的另一个想法是使用默认应用程序域的AppDomain.UnhandledException事件,但我怎么能这样:

    1. 发现原产地的AppDomain,以及要卸载的模块吗?
    2. 防止应用程序死亡? (我试过这样做,e.IsTerminating带有真正的价值,而且异常仍然存在于
    3. 任何?拜托,我真的需要它。

1 个答案:

答案 0 :(得分:0)

对于AppDomain.CurrentDomain.UnhandledException处理程序为什么不抑制未处理的异常here,有一个相当不错的解释(带有支持链接)。您链接到的MSDN文章也会在您引用的部分下方描述此行为。

  

在.NET Framework 1.0和1.1版中,出现未处理的异常   发生在主应用程序线程以外的线程中   由运行时捕获,因此不会导致应用程序   终止。因此,UnhandledException事件可能是   在没有申请终止的情况下提出。从.NET开始   框架版本2.0,这个支持未处理的子例外   线程被删除了,因为这种沉默的累积效应   失败包括性能下降,数据损坏和   锁定,所有这些都很难调试。

因此,即使您可以将事件触发,也不太可能满足您的要求,即应用程序不会在不久之后终止。 UnhandledException处理程序实际上只是为了给你最后一次机会在应用程序终止之前记录重要信息。

最具弹性的应用程序(例如Google Chrome)将使用完全进程隔离来确保插件中出现任何问题的内容都会破坏外部插件主机,而不是主应用程序。我自己使用这种机制来创建一个类似于你描述的应用程序,甚至在每个外部插件主机中创建沙盒AppDomain的程度,以确保在主应用程序被提升时插件无法删除关键文件。 / p>

有一篇非常好的文章here详细描述了隔离技术,并重申由于UnhandledException问题,AppDomain插件系统不是最佳选择。如果您认真考虑容错插件架构,我建议实现上一篇文章中描述的完整进程隔离。