使用应用程序域中.模块化表单应用程序中的UnhandledException

本文关键字:应用程序 UnhandledException 表单 模块化 应用程序域 | 更新日期: 2023-09-27 17:52:45

我目前正在开发一个完全模块化的。net应用程序,其中:

    这是加载模块ddl的主机应用程序。模块ddl具有可以多次打开的表单。
  1. 您可以卸载应用程序域。这将导致模块所有打开的表单被关闭。

我想做的是,当模块中发生未处理的异常时,应用程序应该卸载该模块的DDL并防止主机崩溃。

我试图使用AppDomain。事件创建后,将为其分配一个处理程序AppDomain如下:

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

问题是:处理程序永远不会被调用。微软在这里说

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

即使在我分配处理程序之后,异常仍然转到

应用程序。运行(新HostForm ());

我想,如果我为每个模块的形式创建了一个新的消息循环,它将工作,因为然后该形式将运行的线程将是一个分离的线程,但它似乎是一个愚蠢的解决方案。

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

  1. 发现源的AppDomain,从而发现要卸载的模块?
  2. 防止应用程序死亡?(我试着这样做,e.isterating带有真正的值,异常仍然被捕获在

有人知道吗?

使用应用程序域中.模块化表单应用程序中的UnhandledException

关于为什么AppDomain.CurrentDomain.UnhandledException处理程序没有在这里抑制未处理的异常,这里有一个相当好的解释(带有支持链接)。你所链接到的MSDN文章也描述了这种行为,就在你引用的部分下面。

在。net框架1.0和1.1版本中,一个未处理的异常发生在主应用程序线程以外的线程中由运行时捕获,因此不会导致应用程序终止。因此,UnhandledException事件可能是在应用程序不终止的情况下引发。从。net开始框架2.0版,这是对child中未处理异常的支持线程被移除了,因为这样的累积效应是无声的故障包括性能下降、数据损坏和锁,所有这些都很难调试。

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

最有弹性的应用程序(例如Google Chrome)将使用全进程隔离来确保插件中的任何错误都会破坏外部插件主机,而不是主要应用程序。我自己用这种机制创建了一个类似于你描述的应用程序,甚至在每个外部插件主机中创建了沙盒AppDomain,以确保当主应用程序被提升时,插件不能删除关键文件。

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