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

标签 c# .net winforms module appdomain

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

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

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

我尝试使用 AppDomain.UnhandledException 事件,它在创建 AppDomain如下:

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

问题是:永远不会调用处理程序。微软说here那个

For example, suppose a thread starts in application domain "AD1", calls a method in application domain "AD2", and from there calls a method in application domain "AD3", where it throws an exception. The first application domain in which the UnhandledException event can be raised is "AD1". If that application domain is not the default application domain, the event can also be raised in the default application domain.

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

Application.Run(new HostForm());

我想,如果我为每个模块的表单创建一个新的消息循环,它就会起作用,因为这样运行表单的线程将是一个单独的线程,但这似乎是一个愚蠢的解决方案。

我的另一个想法是使用默认应用程序域的 AppDomain.UnhandledException 事件,但我该如何:

  1. 发现原始 AppDomain 以及要卸载的模块?
  2. 防止应用程序死亡? (我试过这样做并且 e.IsTerminating 带有真实值并且异常仍然被捕获在

有人吗?拜托,我真的需要它。

最佳答案

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

In the .NET Framework versions 1.0 and 1.1, an unhandled exception that occurs in a thread other than the main application thread is caught by the runtime and therefore does not cause the application to terminate. Thus, it is possible for the UnhandledException event to be raised without the application terminating. Starting with the .NET Framework version 2.0, this backstop for unhandled exceptions in child threads was removed, because the cumulative effect of such silent failures included performance degradation, corrupted data, and lockups, all of which were difficult to debug.

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

最具弹性的应用程序(例如谷歌浏览器)将使用完整的进程隔离来确保插件中出现的任何错误都会破坏外部插件主机,而不是主应用程序。我自己使用这种机制创建了一个与您描述的应用程序类似的应用程序,甚至达到了在每个外部插件主机内创建沙盒 AppDomain 的程度,以确保插件在主应用程序被提升时无法删除关键文件。

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

关于c# - 在模块化表单应用程序中使用 AppDomain.UnhandledException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5780561/

相关文章:

c# - 使用 Visual Studio 和 .NET Framework 进行多目标构建

c# - 如何在 Entity Framework 核心 rc2 中实现类型安全枚举模式

c# - 序列化匿名委托(delegate)列表

winforms - 如何在 Winforms 应用程序中使标签文本可缩放

c# - 清除没有循环的 TableLayoutPanel 的列?

c# - .NET framework 是否支持根据 UNIX 时间戳获取以秒为单位的当前时间?

c# - 如何访问 Razor 引擎 View 文件中的 C# 类属性?

c# - 如何将 float 组转换为 byte[] 并返回?

c# - 在 mschart 中的列顶部显示 X 值

C# 方法/属性的异常实例化