.net Castle Windsor拦截器内存泄漏
在使用Castle Windsor和拦截器时,我遇到了一个程序内存不足的问题。可使用以下代码进行复制:.net Castle Windsor拦截器内存泄漏,.net,memory-leaks,castle-windsor,.net,Memory Leaks,Castle Windsor,在使用Castle Windsor和拦截器时,我遇到了一个程序内存不足的问题。可使用以下代码进行复制: public interface ITest{} public class Test : ITest {} class TestInterceptor:IInterceptor { public void Intercept(IInvocation invocation) {} } class Program { static void Main(string[] args)
public interface ITest{}
public class Test : ITest {}
class TestInterceptor:IInterceptor {
public void Intercept(IInvocation invocation) {}
}
class Program {
static void Main(string[] args) {
while(true) {
using(var container = new WindsorContainer()) {
container.Register(Component.For<TestInterceptor>());
container.Register(Component.
For<ITest>().
ImplementedBy<Test>().
Interceptors(
InterceptorReference.ForType<TestInterceptor>()
).Anywhere);
var tst = container.Resolve<ITest>();
}
}
}
}
公共接口ITest{}
公共类测试:ITest{}
类测试接收器:I接收器{
公共无效拦截(IInvocation调用){}
}
班级计划{
静态void Main(字符串[]参数){
while(true){
使用(var container=new WindsorContainer()){
container.Register(Component.For());
容器。寄存器(组件)。
For()。
由()实现。
拦截器(
InterceptorReference.ForType()
)(任何地方);
var tst=container.Resolve();
}
}
}
}
这就是内存使用的发展过程:
因此,让我感到不快的是,我认为存在非托管代码内存泄漏,但经过大量调试后,我发现问题出在拦截器prxoy生成上:每次解决问题时,都会向运行时引入一个新的(动态)具有代理类型的程序集:
现在,我想你可以通过
ProxyGenerator
自己生成代理,并使用UsingFactoryMethod
生成实例的方式(我现在这样做)- 容器针对这种情况进行了高度优化。通常使用Reflection.Emit生成委托,并缓存信息。这会一次性影响性能(每个容器实例),并加速所有后续请求。每个请求创建一个新实例可能会耗尽应用程序的性能,因为所有这些反射和代码发出都会一次又一次地发生
- 但除了这种优化,注册过程本身也需要时间。这可能是一次性的成本,但你要一次又一次地这么做
- 配置容器可能变得更加困难。注册应该比请求寿命长的实例要困难得多。有很多方法可以解决这个问题,但这通常会导致容器配置难以掌握、难以维护并且存在bug。Castle Windsor包含允许验证容器的,但不能进行跨容器验证的
- 仔细阅读使拦截器始终处于瞬时状态。
正确的代码是:
public interface ITest{}
public class Test : ITest {}
class TestInterceptor:IInterceptor {
public void Intercept(IInvocation invocation) {}
}
class Program {
static void Main(string[] args) {
while(true) {
using(var container = new WindsorContainer()) {
container.Register(Component.For<TestInterceptor>().LifestyleTransient());
container.Register(Component.
For<ITest>().
ImplementedBy<Test>().
Interceptors(
InterceptorReference.ForType<TestInterceptor>()
).Anywhere);
var tst = container.Resolve<ITest>();
}
}
}
}
公共接口ITest{}
公共类测试:ITest{}
类测试接收器:I接收器{
公共无效拦截(IInvocation调用){}
}
班级计划{
静态void Main(字符串[]参数){
while(true){
使用(var container=new WindsorContainer()){
container.Register(Component.For().LifestyleTransient());
容器。寄存器(组件)。
For()。
由()实现。
拦截器(
InterceptorReference.ForType()
)(任何地方);
var tst=container.Resolve();
}
}
}
}
我今天遇到了同样的问题。为了回答原始帖子中的第3个问题,性能计数器[.NET Clr Loading->Current Assembly]在运行代码片段时,由于加载的是动态代理类型,程序集的数量会线性增加。我想你是对的。在这样做时,很容易引入内存泄漏和线程安全问题。前2点可以通过显式允许缓存该工作来减轻。@Freek,该工作已缓存。它缓存在容器实例中。在AppDomain级别缓存它本身会导致内存泄漏。是的,这是我理解的部分。但我的意思是缓存可以显式地工作,以便在实例化新容器实例时可以利用缓存步骤。IIRC这很像NHibernates SessionFactory/会话分离。当只有一个容器实例时,不应该“很容易引入内存泄漏”,因为默认情况下,所有注册都应该是暂时的。在这种情况下,每个请求一个容器和每个应用程序域一个容器之间的生命周期(和风险)没有区别,也没有线程安全问题。但在温莎,默认情况下是单例,容器跟踪(可能)瞬态。所以,如果你自己解决了一个暂时的问题(这可能是一个坏主意),并且在使用后不释放它,那么你将面临内存问题。尽管这可能会耗尽应用程序的性能,但为每个请求创建一个容器实例不会导致内存泄漏。您尝试过这个吗?它有完全相同的问题。