编程语言
首页 > 编程语言> > C#-简单注入器-装饰器导致容器未被垃圾收集?

C#-简单注入器-装饰器导致容器未被垃圾收集?

作者:互联网

我注意到,当我通过简单的注入器添加装饰器时,该容器不会超出范围.有人知道这是否可以预期吗?如果我不添加装饰器,则说明该容器是垃圾收集的.否则,不是.我应该采取什么措施来强制清理?

这是一个简单的例子.如果添加了装饰器,则在“运行”完成后,容器仍在内存中.如果未添加装饰器,则容器将进行GC处理.

public interface IDoSomething { }
public class DoSomething: IDoSomething { }
public class DoSomethingDec1: IDoSomething {
    public DoSomethingDec1(IDoSomething handler) { }
}
public class DoSomethingDec2 : IDoSomething {
    public DoSomethingDec2(IDoSomething handler) { }
}

static void Main(string[] args) {
    Console.WriteLine("Press a key to start");
    Console.ReadKey(true);
    Run();
    GC.Collect();
    Console.WriteLine("Done");
    Console.ReadKey(true);
}

static void Run() {
    //can be re-created with 1 container; easier to see with multiple
    for (var i = 0; i < 1000; i++) {
        using (var container = new Container()) {
            container.Register<IDoSomething, DoSomething>();

            //Comment out these 2 lines to remove the decorators
            container.RegisterDecorator<IDoSomething, DoSomethingDec1>();
            container.RegisterDecorator<IDoSomething, DoSomethingDec2>();

            container.Verify();

            container.GetInstance<IDoSomething>();
        }
    }
}

带装饰器:

enter image description here

没有装饰器:

enter image description here

解决方法:

更新:此问题已在v3.1.1中修复.

该问题是由bug in the .NET framework引起的,如果该图包含ThreadLocal< T&gt ;,则该对象使循环对象图保持活动状态.在简单注入器的情况下,装饰器子系统添加ThreadLocal< T>.到“容器的项目”字典中. ThreadLocal的值再次间接引用了Container,从而导致图形变为循环的.由于.NET中的错误,因此ThreadLocal< T>被认为是活动的,保持其依赖对象(例如Container)活动. Container实例再次使其他所有内容保持活动状态,这显然会导致内存泄漏.

尽管我们可以等待Microsoft解决此问题,但这可能会花费太长时间.因此,我们的计划是在将来的修补程序版本中解决此问题.我们可能会替换.NET的ThreadLocal< T>.使用我们自己的自定义实现,不会导致内存泄漏.该自定义实现已在Simple Injector的PCL库中使用,因为ThreadLocal< T>不适用于PCL.这意味着PCL版本的Simple Injector不存在此问题.

标签:dependency-injection,memory-leaks,c,simple-injector
来源: https://codeday.me/bug/20191119/2037255.html