wpf 如何避免内存泄漏与Autofac?

tjrkku2a  于 2023-03-09  发布在  其他
关注(0)|答案(1)|浏览(266)

我试图更好地理解IoC/DI,特别是作用域的概念。
我正在使用Pluralsight course(很棒的服务,顺便说一句)中的一个示例WPF应用程序(repo here),并对其进行了轻微的修改。
以下是original code

Private Sub App_Startup(Sender As App, e As StartupEventArgs) Handles Me.Startup
  Dim oBootStrapper As BootStrapper
  Dim oContainer As IContainer
  Dim oMainView As MainView

  oBootStrapper = New BootStrapper
  oContainer = oBootStrapper.GetContainer
  oMainView = oContainer.Resolve(Of MainView)
  oMainView.Show()
End Sub

......我把它改成了:

Private Sub App_Startup(Sender As App, e As StartupEventArgs) Handles Me.Startup
  Dim oBootStrapper As BootStrapper
  Dim oContainer As IContainer
  Dim oMainView As MainView

  oBootStrapper = New BootStrapper
  oContainer = oBootStrapper.GetContainer

  Using oScope As ILifetimeScope = oContainer.BeginLifetimeScope
    oMainView = oScope.Resolve(Of MainView)
    oMainView.Show()
  End Using
End Sub

但是,当我尝试添加新朋友时,这会导致ObjectDisposedException

无法解析示例,也无法从此LifetimeScope创建嵌套生存期,因为它(或其父范围之一)已被释放。
这一切似乎与我在官方文件中发现的内容相矛盾:
务必始终从生存期范围而非根容器解析服务。
这一指导使我首先引入了作用域。但是,如果作用域部署了应用程序运行所必需的对象,那么我们如何希望使用它呢?此外,我们为什么要使用它呢?
我糊涂了。我提议的用法不对吗?

  • --编辑--*

澄清一下,我正在寻找官方指南所提出的难题的解决方案:如果我们坚持这一点,我们的应用程序将失败。但如果我们不这样做,我们的风险内存泄漏(根据文档)。
怎么办?

f0brbegy

f0brbegy1#

    • 官方指南可帮助您防止意外的内存泄漏。**由于Autofac持有对可处置内容的引用,因此它可以执行处置,如果您直接从容器中解析1000个IDisposable项,则无法让垃圾收集在不处置整个容器的情况下清理它们。

如果你没有考虑到这一点,比如说,有一个长时间运行的应用偶尔会处理数据库--这些工作可能会周期性地从容器中解析一个可释放的数据库上下文,即使调用代码执行dispose,容器也会挂起它:内存泄漏。
然而,把它和关于单例的文档放在一起。单例,即使你从一个子作用域解析它们,* 仍然存在于容器根 *。为什么?因为如果你让一个作用域处理一个共享的单例,那么对于其他需要单例的东西来说,这将是一个问题。
"从作用域解决问题"指导是为了防止人们搬起石头砸自己的脚,因为他们没有意识到他们只使用容器就引入了内存泄漏。
如果您正在解析的东西不是可释放的,并且在整个依赖链中没有任何东西是可释放的,那么您 * 可能 * 会安全地从容器中获取它。
这里更大的教训是要努力与您的生存期范围和您希望如何处置处理。我不是一个WPF的家伙,但如果应用程序的主窗口需要解决,并需要生存的整个应用程序的持续时间,看起来这是单例的完美用法......它不会在生存期结束时被处理,您也不会看到异常。Autofac也有一些方法可以选择不让它进行处置,这会阻止它保存那些引用。
但是很难说"总是做这个"和"从不做那个",因为正如你所看到的,生存期范围和处置是一个复杂的主题。深入研究 * 为什么 * 是很重要的,内存管理和处置就是原因。出于同样的原因,正确获得注册组件的生存期也同样重要。

相关问题