Dmy*_*tov 5 c# memory-leaks .net-core
我试图在我的应用程序中调试内存泄漏(请参阅相关问题)并且遇到了一个微笑错误的行为。
在这段代码中(当然是简化的片段):
while (true)
{
using (var context = _serviceProvider.GetRequiredService<IDataContext>())
{
Console.WriteLine("Hello");
}
}
Run Code Online (Sandbox Code Playgroud)
内存消耗快速增长。
如果我注释掉 service spawn,内存消耗是稳定的。
while (true)
{
// using (var context = _serviceProvider.GetRequiredService<IDataContext>())
// {
Console.WriteLine("Hello");
// }
}
Run Code Online (Sandbox Code Playgroud)
服务已注册为瞬态。
我的理解是using声明负责处理服务。var context在 范围内创建,while并且应该在新迭代开始时销毁。
我的第一个想法是 GC 只是没有足够频繁地完成它的工作,但是当消耗的内存量增加时频率不会增加?
为什么我错了?
经过几天的斗争,我终于得出了答案。简而言之,问题在于 Microsoft DI 容器不处理瞬态服务,而是保留对它们的引用。
这是github上的相应问题。
开发人员不打算修复它,因为修复的成本(复杂性和黑客性)超过了收益。
建议的解决方法是使用范围服务而不是临时服务。
这是一个示例代码,请参阅issue 中的更多内容。
using (var scope = serviceProvider.CreateScope())
using (var context = scope.ServiceProvider.GetRequiredService<IDataContext>())
{ ... }
Run Code Online (Sandbox Code Playgroud)
小智 5
只是想指出,从瞬态服务切换到范围服务可能还不够。在我的应用程序中,根本不需要。
\n\n我的问题是,正如您在回答中已经说过的,ServiceProvider会跟踪它创建的所有对象。\n长时间运行的应用程序和从未释放的容器会导致巨大的内存消耗。即使容器仅创建快速运行“超出范围”的瞬态对象(甚至不是 IDisposable)。由于 ServiceProvider 仍在跟踪这些对象,因此 GC 无法完成其工作。
\n\n考虑按照建议使用作用域 ServiceProvider,因为处置它也会结束其所有子项(作用域和瞬态)的生命周期。\nDon\xe2\x80\x99t 让容器(子项)超出范围。即使对于瞬态对象也可以使用作用域 ServiceProvider。
\n| 归档时间: |
|
| 查看次数: |
2439 次 |
| 最近记录: |