我正在使用MEF(.Net Framework 中的MEF,而不是System.Composition Nuget)在asp.net 中进行DI。我遇到了内存泄漏,就像许多人以前遇到的那样,由于 MEF rooting NonShared IDisposable (例如 link )
我正在考虑使用子容器来纠正这个问题
- 子容器创建特定于单个请求的(非共享)部分
- 包含共享部分的父容器(称为导出提供程序)
所以类似:
CompositionContainer GetRequestContainer(CompositionContainer parent, ComposablePartCatalog catalog)
{
return new CompositionContainer(catalog, parent);
}
<小时/>
最初,我构建了一个包含共享和非共享部分的单一目录:为了创建仅包含非共享部分的子容器,我使用了 FilteredCatalogs基于父 CompositionContainer 的目录构建,以便过滤后的目录仅包含非共享部分。
这解决了内存泄漏,因为我可以在请求结束时 Dispose() 子容器,然后释放所有非共享 IDisposable 对象。伟大的。
但是,调用 childContainer.GetExportValues 会返回重复项,因为存在来自父容器目录和子容器目录的部分。
<小时/>现在我想明确创建 2 个目录:
- 所有共享部件的全局目录
- 所有非共享部件的本地目录
我怀疑 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);
}
最佳答案
将同一个目录实例与多个 CompositionContainer
实例一起使用是完全安全的(顺便说一句,无论您是否在以下情况下使用 CompositionOptions.IsThreadSafe
选项,这都是正确的)创建容器)。
这样做是安全的,因为目录仅定义了容器可以创建的部件的“潜力”,并且不保存有关它们是否已实例化的任何数据。容器有责任跟踪这些事情。
关于asp.net - 线程安全和 MEF 目录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23448218/