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>();
}
}
}
带装饰器:
没有装饰器:
解决方法:
更新:此问题已在v3.1.1中修复.
该问题是由bug in the .NET framework引起的,如果该图包含ThreadLocal< T> ;,则该对象使循环对象图保持活动状态.在简单注入器的情况下,装饰器子系统添加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