线程安全和MEF目录

4
我正在使用MEF(.Net Framework中的一个,而不是System.Composition Nuget)在asp.net中进行DI。像许多人以前遇到的那样,我遇到了内存泄漏问题,这是由于MEF固定了NonShared IDisposable (例如link)。
我打算使用子容器来纠正这个问题,方法如下:
1.子容器创建(非共享)特定于单个请求的部件。
2.父容器(作为导出提供程序引用),包含共享的部分。
因此,大致的实现方法如下:
CompositionContainer GetRequestContainer(CompositionContainer parent, ComposablePartCatalog catalog)
{
    return new CompositionContainer(catalog, parent);
}

最初,我建立了一个包含共享和非共享部分的单个目录:为了创建一个仅包含非共享部分的子容器,我使用了从父CompositionContainer的目录构建的FilteredCatalogs,以便过滤的目录仅包含非共享的部分。

这解决了内存泄漏问题,因为在请求结束时我可以Dispose()子容器,这将释放所有我的非共享IDisposable对象。太好了。

但是,调用childContainer.GetExportValues会返回重复项,因为父容器的目录和子容器的目录中都有部分内容


现在我想明确创建两个目录:

  • 全局目录用于所有共享部分
  • 本地目录用于所有非共享部分

我怀疑IDisposable跟踪是在容器级别进行的,所以我应该安全地传递每个目录的单个实例,但这就是我想在这里询问并确认的:

是否线程安全地拥有支持所有容器实例的单个目录实例

因此,N并发 WebRequest实例由N + 1 CompositionContainer实例(子+父)服务,所有这些实例都由2个全局目录实例支持。

CompositionContainer parent = new CompositionContainer(Static.Global, CompositionOptions.IsThreadSafe);

CompositionContainer GetRequestContainer(CompositionContainer parent)
{
    return new CompositionContainer(Static.Local, parent);
}
1个回答

1
使用相同的目录实例与多个CompositionContainer实例完全安全(顺便说一下,这是真实的,无论您在创建容器时是否使用CompositionOptions.IsThreadSafe选项)。
之所以安全,是因为目录仅定义了容器可以创建的部件的“潜力”,并且不保存任何关于它们是否已被实例化的数据。跟踪此类事物是容器的责任。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接