我正在开发一个大型应用程序,它由许多较小的插件/应用程序组成。
它们不够大,不足以成为一个完整的进程,但是太小,不能在线程中运行,在一个进程下,以及我希望它基于插件的基础上。如果该插件的更新版本可用,则应该卸载、更新并重新启动。
在我寻找解决方案的过程中,我可以理解“AppDomain”这个神奇的词,我引用如下:
“使用应用程序域隔离可能会导致进程中断的任务。如果正在执行任务的AppDomain的状态变得不稳定,则可以卸载AppDomain而不影响进程。当进程必须长时间运行而不重新启动时,这一点很重要。还可以使用应用程序域隔离不应该共享数据的任务。”
因此,这正是我想要的。然而,我想他们的“状态变得不稳定”是一个与我不同的观点。我想到了一个问题,其中一个插件抛出了一个异常,不管是什么原因。我希望被捕获,电子邮件,卸载和重新启动(如果可能的话)。
因此,我创建了一个启动的应用程序,查找其文件夹中的所有..dll。检查dll是否由插件组成。为该插件创建一个新的AppDomain,一旦加载所有插件,它将启动每个插件。(其中每个插件都可以由多个线程组成,与其他插件一起愉快地共存)。
因此,我还在其中添加了一个超时,它在5秒后触发以引发一个新的异常();在AppDomain上添加了一个UnhandledException事件来处理它。但是,它抓住了它,并在呼叫之后,仍然“崩溃”了整个过程,包括所有额外的孩子-阿普曼。
但它在引语中清楚地指出,“隔离”那些“可能”会导致进程崩溃的任务。所以我错过了什么重要的东西吗?我对这句话的看法是否错误?
发布于 2011-08-15 23:53:45
自从.NET 2.0 未处理的异常会导致进程崩溃。。来自AppDomain.UnhandledException事件文档:
此事件提供非正常异常的通知。它允许应用程序在系统默认处理程序向用户报告异常和终止应用程序之前记录有关异常的信息。
AppDomain.FirstChanceException也是如此
此事件仅为通知。处理此事件不会以任何方式处理异常或影响后续异常处理。
您需要考虑如何处理异常,就像在普通应用程序中那样。仅仅使用AppDomains是没有帮助的。如果未在给定的AppDomain中处理异常,则将在调用AppDomain时重新引发该异常,直到它得到处理或使进程崩溃为止。处理一些异常并不要让它们破坏您的进程是非常好的。
AppDomain是程序集和内存(而不是线程)的逻辑容器。AppDomain的隔离意味着:
使用AppDomain最常见的原因是在运行不受信任的第三方代码时。或者您有非托管代码,并且希望承载CLR或需要dll热交换。我认为在CLR主机场景中,当第三方代码抛出未处理的异常时,您可以避免崩溃。
另外,您可能希望查看System.Addin或MEF,而不是滚动您自己的基础设施。
发布于 2011-08-16 01:03:03
未处理的异常有两个问题。AppDomain只解决其中一个问题。你在试着对付另一个。
好消息先来。当您处理异常时,您必须恢复程序状态,就好像该异常从未发生过一样。所有的一切都必须被还原到代码运行之前的状态。通常会有一堆catch和state子句来撤消代码所执行的状态突变。当然没什么很简单的。但如果不处理例外情况则是完全不可能的。你不知道到底发生了什么变异,以及如何恢复它。AppDomain以冷静的方式处理这个非常困难的问题。你卸下它,剩下的任何状态都会消失。没有垃圾收集堆,也没有加载程序堆(静力学)。在创建AppDomain之前,整个enchilada都会被重置为任何状态。
太好了。但还有一个问题也很难解决。你的程序被要求执行一项任务。线程开始执行那项工作。但它心脏病发作了。第一个大问题:线死了。如果你的程序一开始只有一个线程,那真是个坏消息。没有线程了,程序终止了。很好,AppDomain首先卸载,但它真的没有任何区别,它会得到卸载无论如何。
这也是个大问题:完成这项工作是非常重要的。但事实并非如此,重要的是,比如说,平衡公司损益表。这件事没有完成,必须有人来处理这件事,因为不平衡声明会让很多人非常生气。
你怎么解决这个问题?
只有少数几种情况是可以接受的。服务器场景。有人要求它做一些事情,服务器报告返回“做不到,请与系统管理员联系”。ASP.NET和Server的工作方式。他们使用AppDomains来保持服务器稳定。让系统管理员来处理这些问题。您必须创建这样的支持系统,以使AppDomains为您工作。
发布于 2013-01-16 18:35:37
只是为那些考虑(亲自参与)使用应用程序域的人添加一些关于这个主题的额外信息,主要是为了保证应用程序的稳定性:
几年前,System.AddIn团队发表了一篇非常有趣的博客文章。使用AppDomain隔离检测外接程序故障。
说明只有进程外外接程序才能保证主机的稳定性.更具体而言:
从CLRv2.0开始,子线程上的未处理异常现在将导致整个进程被删除,因此主机不可能完全恢复。
因此,他们建议的是订阅AppDomain.UnhandledException,在应用程序崩溃之前,将其存储在某个地方(日志、数据库等)。有关是谁造成此异常的信息。然后,下次应用程序开始时,使用这些信息来保护应用程序。也许您没有加载外接程序,或者您通知用户并让她/他来决定。(Microsoft Office应用程序遵循这种方法并禁用了崩溃主机的插件。然后,你不得不自己重新启用它们。)
他们还发布了另一篇博客文章,展示了如何做到这一点,即使在主机在另一个主机上运行的情况下(IIS、WAS等)。有关从托管外接程序中记录UnhandledExeptions的更多信息。。
虽然这两篇文章都以System.AddIn为中心,但对于任何试图提高其插件感知应用程序稳定性的人来说,它们都包含了有用的信息。
https://stackoverflow.com/questions/7071957
复制相似问题