我是Ninject的新手,但我已经确信Ninject.MVC5 NuGet包的开箱即用配置从未真正释放作用于HttpContext的对象。在我的一些较大的报告重复使用大量内存之后,我一直得到一个OutOfMemoryException。
为了证明我没有失去理智,我创建了一个空的测试项目。我在VS 2017中通过文件创建了一个默认项目 - >新项目 - > C# - >网络 - > ASP.NET Web应用程序 - > MVC(在模态中)。这也是一个新的解决方案,需要明确。然后我安装了Ninject 3.2.2(不是最新的; Ninject.MVC5需要< 3.3),然后安装了Ninject.MVC5。
然后我去了HomeController.cs并首先在文件的底部添加了一个类:
public class MemoryEater : IDisposable
{
public List<int> _nums = new List<int>();
public MemoryEater()
{
var rand = new Random(); // Use random so that I get a bit of CPU usage I can see in Task Manager
for (int cnt = 0; cnt < 2_500_000; ++cnt)
{
var key = rand.Next();
_nums.Add(key);
}
}
public void Dispose()
{
if (_nums != null)
_nums = null;
}
}
然后我向HomeController添加了一个构造函数:
public class HomeController : Controller
{
readonly MemoryEater _me;
public HomeController(MemoryEater me)
{
_me = me;
}
最后我打开了NinjectWebCommon.cs,直到现在我都没有修改过(这个文件是通过NuGet安装Ninject.MVC5创建的100%),并在RegisterServices中添加了一行:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<MemoryEater>().ToSelf().InRequestScope();
}
然后我使用IISExpress运行应用程序并在Chrome中查看(在Windows 10上)。我刷新页面并观察内存使用率的上升;随着内存使用量的下降,一些GC发生得很清楚,这是预期b / c List对象必须增长的。但它继续攀升超过600MB,经过几十次刷新后,我的应用程序中出现OutOfMemoryException。
所以我更进了一步,将源代码从GitHub for OnePerRequestHttpModule.cs复制到我项目中的一个新文件中,然后拆分方法DeactivateInstancesForCurrentHttpRequest,这样我就可以在一个断点处调用ICache.Clear:
public void DeactivateInstancesForCurrentHttpRequest()
{
if (this.ReleaseScopeAtRequestEnd)
{
var context = HttpContext.Current;
this.MapKernels(kernel => ClearCacheOfContext(kernel, context)); // BREAKPOINT A
}
}
private void ClearCacheOfContext(IKernel kernel, HttpContext context)
{
kernel.Components.Get<ICache>().Clear(context); // BREAKPOINT B
}
我更改了NinjectWebCommon以使用我的新OnePerRequestHttpModule副本,并在A和B处放置断点。每次调用请求A后,B 从不调用。
我做错了什么或这是一个合法的错误?这个错误可能存在对我来说似乎是不可想象的,而我,Ninject的n00b,可能是第一个找到它的人。
答案 0 :(得分:2)