哇谢谢。我也尝试过解决这个问题,尽管方法更简单,但我已经确认内存使用量显着减少。我在 BeginScope 方法中创建了一个 MefDependencyResolver,而不是像我们在其他示例中看到的那样返回“this”,而是根据 mef codplex 站点http://mef.codeplex.com/中所示的过滤目录创建了一个子容器wikipage?title=Filtering%20Catalogs&referringTitle=Parts%20Lifetime。
我的 WebAPI 测试项目首先使用实体框架代码将实体存储在数据库中。
我创建了一个测试客户端将 15000 个实体 POST 到数据库中,在每个测试中我运行 3 个并发客户端,重复测试 3 次。随着开始范围返回“this”和 Dispose 方法中的 NOOP,我将分配给 ApplicationPool 的内存用尽了。通过基于过滤的目录返回一个新容器并在 Dispose 方法中处理该容器并重复测试内存增加到 600MB 并保持在那里 IIS 保持正常并且没有发生池回收。
public class MefDependencyResolver : System.Web.Http.Dependencies.IDependencyResolver, System.Web.Mvc.IDependencyResolver
{
protected CompositionContainer _container;
public MefDependencyResolver(CompositionContainer container)
{
_container = container;
}
public IDependencyScope BeginScope()
{
var filteredCat = new FilteredCatalog(_container.Catalog,
def => def.Metadata.ContainsKey(CompositionConstants.PartCreationPolicyMetadataName) &&
((CreationPolicy)def.Metadata[CompositionConstants.PartCreationPolicyMetadataName]) == CreationPolicy.NonShared);
var child = new CompositionContainer(filteredCat, _container);
return new MefDependencyResolver(child);
}
/// <summary>
/// Called to request a service implementation.
///
/// Here we call upon MEF to instantiate implementations of dependencies.
/// </summary>
/// <param name="serviceType">Type of service requested.</param>
/// <returns>Service implementation or null.</returns>
public object GetService(Type serviceType)
{
if (serviceType == null)
throw new ArgumentNullException("serviceType");
var name = AttributedModelServices.GetContractName(serviceType);
var export = _container.GetExportedValueOrDefault<object>(name);
if (export != null)
{
Trace.WriteLine("PAUSE");
}
return export;
}
/// <summary>
/// Called to request service implementations.
///
/// Here we call upon MEF to instantiate implementations of dependencies.
/// </summary>
/// <param name="serviceType">Type of service requested.</param>
/// <returns>Service implementations.</returns>
public IEnumerable<object> GetServices(Type serviceType)
{
if (serviceType == null)
throw new ArgumentNullException("serviceType");
var exports = _container.GetExportedValues<object>(AttributedModelServices.GetContractName(serviceType));
return exports;
}
#region IDisposable
private bool _disposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing) // Managed:
{
//NOOP since MEF does not have the idea of a Scoped Container (except it does have a concept of a filtered container!)
//
Trace.WriteLine("DISPOSING MEF CONTAINER.");
this._container.Dispose();
this._container = null;
}
// Unmanaged:
_disposed = true;
}
}
~MefDependencyResolver()
{
Dispose(false);
}
#endregion
}