4

ninject内のweakreferencecollectionにオブジェクトが破棄されない場合のメモリリーク、何が間違っているのですか、それともninjectに大きなエラーがありますか?

カーネルが破棄されると、weakreference コレクションからすべての参照が破棄されますが、このループでは、コードからの参照がない場合でも、メモリが爆発します。

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
    {
    }
}

アップデート

私は Named スコープで試してみましたが、例のように Factory を使用することさえしました: 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 が終了するのを待ちません。そんなに気になるなら電話した方GC.WaitForPendingFinalizers()がいいよ。

于 2013-05-27T21:01:23.343 に答える