内存泄漏时,没有对象在ninject内部的weakreferencecollection中处理,我做错了什么或者ninject中有一个巨大的错误?
当Kernal被释放时,所有引用都会从弱引用集合中被释放,但是在此循环中,即使没有代码引用 - 内存也会爆炸。
public class Program
{
private StandardKernel kernel;
private static void Main(string[] args)
{
new Program().Run();
}
public void Run()
{
kernel = new StandardKernel(new NinjectSettings() { LoadExtensions = false });
kernel.Bind<Root>().ToSelf();
kernel.Bind<Foo>().ToSelf().InCallScope();
while (true)
{
Process();
Thread.Sleep(500);
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
public void Process()
{
Root root = kernel.Get<Root>();
Root root2 = kernel.Get<Root>();
}
public class Root
{
private Foo _test;
public Root(Foo foofac)
{
Id = Guid.NewGuid();
_test = foofac;
}
protected Guid Id { get; set; }
}
public class Foo
{
}
}
我尝试过使用命名范围,甚至在例子中使用工厂: http://www.planetgeek.ch/2012/04/23/future-of-activation-blocks/ 但仍然在memoryprofiler中,弱引用集合随着时间的推移而爆炸,这不太好......我目前的测试代码是:
public class Program
{
private StandardKernel kernel;
private static void Main(string[] args)
{
new Program().Run();
}
public void Run()
{
kernel = new StandardKernel(new NinjectSettings() { LoadExtensions = false });
kernel.Load<FuncModule>();
kernel.Bind<IRootFactory>().ToFactory();
var scopeParameterName = "scopeRoot";
kernel.Bind<Root>().ToSelf().DefinesNamedScope(scopeParameterName);
kernel.Bind<Foo>().ToSelf().InNamedScope(scopeParameterName);
while (true)
{
Process();
GC.Collect();
GC.WaitForPendingFinalizers();
Thread.Sleep(500);
}
}
public void Process()
{
Root root = kernel.Get<IRootFactory>().CreateRoot();
Root root2 = kernel.Get<IRootFactory>().CreateRoot();
}
public class Root
{
private Foo _test;
public Root(Foo foofac)
{
Id = Guid.NewGuid();
_test = foofac;
}
protected Guid Id { get; set; }
}
public class Foo
{
}
public interface IRootFactory
{
Root CreateRoot();
}
}
答案 0 :(得分:1)
这需要时间,而不是确定性的 - 请参阅真实的impl代码和精神的the Cache and Collect article。
在你的例子中,你应该等待Ninject Releasing机制被触发(关闭计时器IIRC)。 def不做的一件事是同步Dispose并释放第二个GC发生。
最重要的是,您最好通过IResolutionRoot.Release
或named scopes allied to InRequestScope
确定性地执行发布。
答案 1 :(得分:1)
不是我建议使用它,但GC.Collect()
是一种异步机制。调用它只会触发GC发生,它不会等待它完成。如果你担心它,你可能想要致电GC.WaitForPendingFinalizers()
。