我有两种形式的非常简单的应用(为测试内存而创建)。解决方案有三个项目。第一个有表格,第二个DAL和第三个ComonLib
。
(所有这些内存数字都来自任务管理器。问题的最后有4个内存分析器的图像)
当我运行我的应用时,内存使用量约为8MB
。这个表单只有两个按钮。一个按钮用于打开第二个表单,另一个按钮用于收集GC
。
当我打开第二张格式时,内存增加到大约550MB
。此表单在Load事件中的此网格中加载了网格和数据(1000s of records
)。
打开第二张表格的代码。
CallWidnows cw = new CallWidnows();
cw.ShowDialog();
cw.Dispose();
加载第二种形式的事件
Customers customers = new Customers();
dataGridView1.DataSource = customers.GetAllCustomers();
关闭第二种形式的事件。
dataGridView1.Dispose();
但是在关闭第二种形式后内存使用量没有变化,内存使用量仍为550MB
等了一分钟左右后,我明确地拨打GC.Collect()
并且只有几MB内存释放并转到530MB
等待一分钟后,我再次打电话给GC.Collect()
,现在记忆归结为40MB
任何人都可以帮我理解这一点 内存使用行为?
为什么要处理表单和网格内存 没有发布?
GC.Collect()
所有的记忆
释放但不是我打电话的时候
第一次?我的原始应用程序有几十种表单和用户控件,我在这个应用程序中遇到内存问题。
一方排队: 最初我有以下方法作为静态方法。
Customers customers = new Customers();
dataGridView1.DataSource = customers.GetAllCustomers();
就像
// Static GetAllCustomers method
dataGridView1.DataSource = Customers.GetAllCustomers();
Memory Profiler图片:
1- Application Starts Memory usage 8MB
2- Second form opens and data loaded - Memory Usage - 550MB
3- Second form closed. Form disposed and grid disposed - Memory Usage still - 550 MB
4- First time GC.Collect called.
感谢。
答案 0 :(得分:1)
释放内存的两个GC是终结器中正在清理内存的标志(例如COM对象,任何需要处理清理的东西)。第一个GC定位对象,但仅调度它们以进行最终化。下一个GC运行它们。您可以在第一个GC之后调用WaitForPendingFinalizers来测试是否为真 - 那么它不应该带两个GC。
对我来说,我使用WinDbg和SOS dll来理解这些问题。您也可以在VisualStudio中加载SOS,但我对WinDbg感觉更舒服。 SOS DLL允许您将对象转储到堆上,并查看它们为什么被植根(即哪个对象使它们保持活动状态并需要处理)。
并非每个人都拥有相同的技能组合,因此可以在此SO问题中找到查找.net泄漏的其他建议:Tool for diagnosing memory leaks in .NET (ASP.NET Application)。