【问题标题】:Unload event for the default AppDomain?默认 AppDomain 的卸载事件?
【发布时间】:2010-12-28 21:49:33
【问题描述】:

每当 any AppDomain 卸载时,我都需要触发一个事件 - 包括默认的进程之一。 AppDomain.DomainUnload 的问题在于它只针对非默认 AppDomain 触发。此外,AppDomain.ProcessExit 的执行时间有限,我不能依赖。

任何关于我如何实现这一目标的建议将不胜感激!

(或者,当后台线程 (Thread.IsBackground == True) 也工作时触发事件。)

【问题讨论】:

  • 你想捕捉什么?您使用的是 ASP.Net、Winforms、WPF 还是控制台?在应用程序、DLL 还是服务中?
  • 一个普通的控制台应用程序。我只想在默认 AppDomain 退出时(即 Main 结束时)触发一个事件。
  • 为什么不把代码放在 Main 的末尾?
  • 如果您要处理在卸载的默认应用程序域之后运行的内容..您认为该代码将在哪个应用程序域中运行?我可能是错的,但对我来说,这就像让一只鸡在它不再活着的时候下蛋...... :D 我认为 .net 只允许主机进程加载的应用程序域的可见性......
  • 理想情况下,该事件会在就在域被卸载之前触发。 :)

标签: c# .net multithreading appdomain


【解决方案1】:

你为什么不把你的代码放在 Main 的末尾?

关于一个事件:

不,卸载应用程序域时不会执行任何事件。如果您是库开发人员,您可以将析构函数添加到您的入口类。但请注意,可能无法正确收集所有内容。阅读此答案:https://stackoverflow.com/a/2735431/70386

【讨论】:

  • 如果它是一个框架,这更像是一个文档问题。告诉您的用户调用您的 Cleanup() 方法或应用程序关闭时调用的任何方法。
  • 同上@jgauffin 的评论。更好的是,有一个 IDisposable 类,以便调用者负责确定性处置。
  • 我想我可以为系统制作某种一次性的上下文,但让它成为静态的感觉更合适,因为它的工作方式有点像 ThreadPool(但在这种情况下,专门用于演员)。
  • 我最终采用了这种方法。这并不完全是我想要的,但无论如何,它以消费者可以推理的方式做我需要的事情。感谢您的意见,伙计们!
  • 更新文档告诉用户调用Cleanup()方法的问题是,用户需要调用Cleanup()方法。我更喜欢该类在 AppDomain 结束时自动处理所需的任务(例如,将内容保存到数据库)。如果用户需要调用一个方法,那么他们根本不会调用它。见鬼,是框架的作者,也是使用它的人,而不想调用它。
【解决方案2】:

http://msdn.microsoft.com/en-us/library/system.appdomain.domainunload%28v=VS.90%29.aspx ..但在卸载域之前再次调用它。

取自http://msdn.microsoft.com/en-us/library/system.appdomain.unload.aspx 在 .NET Framework 2.0 版中,有一个专门用于卸载应用程序域的线程。这提高了可靠性,尤其是在托管 .NET Framework 时。当线程调用 Unload 时,目标域被标记为卸载。专用线程尝试卸载域,并且域中的所有线程都被中止。如果线程没有中止,例如因为它正在执行非托管代码,或者因为它正在执行 finally 块,那么在一段时间后,在最初调用 Unload 的线程中会抛出一个 CannotUnloadAppDomainException。如果无法中止的线程最终结束,则不会卸载目标域。因此,在 .NET Framework 2.0 版中,域不能保证卸载,因为它可能无法终止正在执行的线程。

【讨论】:

  • 它不会为默认的 AppDomain 运行。
  • 这就是重点,唯一知道正在卸载默认域的是加载它的那个..我不认为默认域是由托管代码加载的......
  • 所以你的意思是,除非我启动第二个 AppDomain,否则我无法知道默认的 AppDomain 何时卸载?
  • 这就是我的“想法”,应用程序域是 vm 的核心,因此您需要深入了解内部结构......可能会阅读一本关于 vm 内部结构的好书......
【解决方案3】:

在您的主应用程序周围使用包装器/启动器怎么样?该 AppDomain 可以注意到它的子节点何时结束(通过阻塞、轮询或回调),并且可以执行任何需要的额外操作。

同样,如果 main() 包含启动一个执行所有重要工作的单个线程,那么 main() 也可以执行任何需要的额外工作。

如果您能解释一下您需要做什么来响应每个 AppDomain 终止,也许会有所帮助?可能是您要求做的事情在 AppDomain 级别不合适。

【讨论】:

  • 我需要确定性地处置一系列由我启动的后台线程管理的对象。也许 AppDomainManager 在这里有用?
【解决方案4】:

如果您的目标是干净地处理某些后台线程使用的对象,那么我的建议是:

  1. 当您想要退出应用程序时,向后台线程发出信号,告知它们应该清理并停止。

  2. 在主线程中,使用Thread.Join 等待所有后台线程完成并退出。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-12
    • 1970-01-01
    • 2012-11-06
    • 1970-01-01
    • 2011-01-07
    相关资源
    最近更新 更多