4

当 ninject 内的弱引用集合中没有对象被处理时内存泄漏,我做错了什么或者 ninject 中是否存在巨大错误?

当内核被释放时,所有引用都被释放,来自弱引用集合,但是在这个循环中,即使没有来自代码的引用 - 内存也会爆炸。

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/ 但仍然在内存分析器中,弱引用集合正在爆炸时间,这不好......我目前的测试代码是:

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();
    }
}
4

2 回答 2

1

不是我推荐使用它,而是GC.Collect()一种异步机制。调用它只会触发 GC,它不会等待它完成。GC.WaitForPendingFinalizers()如果您对此感到担忧,您可能会想打电话。

于 2013-05-27T21:01:23.343 回答
1

这需要时间,并且不是确定性的 - 请参阅 impl 代码了解现实,以及Cache and Collect 文章了解精神。

对于您的示例中的开始,您应该等待等待 Ninject 释放机制被触发(关闭计时器 IIRC)。它 def 不做的一件事是在 GC 发生后同步 Dispose 和 Release。

底线是您最好通过IResolutionRoot.Release与.InRequestScope

于 2013-05-27T20:24:54.890 回答