在C#中,我在GC.Collect()
和点击事件
Form1_Load
问题GC.Collect()
似乎在Form_load
但适用于点击事件。为什么?
GC.Collect()
first time inForm1_Load
GC.Collect()
second time inclick event
使用visual studio 2015诊断工具
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
DataTable dt;
private void Form1_Load(object sender, EventArgs e)
{
dt = new DataTable();
dt.Columns.Add("1", typeof(int));
dt.Columns.Add("2", typeof(int));
dt.Columns.Add("3", typeof(int));
for (int i = 0; i < 1000000; i++)
{
DataRow dr = dt.NewRow();
dr[0] = 10;
dr[1] = 1000;
dr[2] = 10000;
dt.Rows.Add(dr);
}
//gc first time
dt = null;
GC.Collect();
}
private void button1_Click(object sender, EventArgs e)
{
//gc sec time
dt = null;
GC.Collect();
}
}
答案 0 :(得分:2)
致电GC.Collect
是您可以做的最糟糕的事情(大约100%的时间)。
GC.Collect
检查应用程序内存中对象的引用计数。由于您将dt
设置为null,因此不应再引用该DataTable
实例。好的,所以垃圾收集“收集”它。但这只意味着它将它放在终结器队列中。你没有调用dt.Dispose
来调用GC.SuppressFinalize(this)
来通知gc这个对象不需要放在终结器队列上。
通过将此对象排队以进行最终化,有一个对DataTable
的新引用,并且该对象向上移动了一代。结果是垃圾收集将使这个内存更长。
通过在按钮处理程序中第二次调用GC.Collect
,你会让事情变得更糟。因为,所有仍然引用的对象都会向上移动一代并保持更长时间。
您应该通过调用DataTable
或将其封装在using语句中来简单地处置dt.Dispose
:
private void Form1_Load(object sender, EventArgs e)
{
using (DataTable dt = new DataTable())
{
dt.Columns.Add("1", typeof(int));
dt.Columns.Add("2", typeof(int));
dt.Columns.Add("3", typeof(int));
//... your code
}
}
即使你这样做,也请不要致电GC.Collect
。让垃圾收集工作,因为它总是知道如何做到这一点。如果需要,它将释放未使用的内存。
有关详细信息,请参阅Understanding Garbage Collection in .NET或this MSDN article。