我的应用程序中存在内存问题。每次我从db获取数据并将其分配给Grid时,内存会增加,有时当进行大量搜索时,内存将达到1 G.B。
可能存在其他内存处理问题但是为了测试搜索和绑定数据反复消耗大量内存我创建了一个新的winforms应用程序并在其上放置一个按钮和一个网格并编写此代码。
private void button1_Click(object sender, EventArgs e)
{
using (SqlConnection con = new SqlConnection(connString))
{
SqlDataAdapter adp = new SqlDataAdapter("select * from supplier", con);
DataSet ds = new DataSet();
con.Open();
adp.Fill(ds);
con.Close();
dataGridView1.DataSource = ds.Tables[0];
ds.Dispose();
}
}
每次点击此按钮,此应用程序的内存使用量都会增加,有时会增加3MB,有时会增加4MB等。表格中的 2000 记录和 12 列的记录不同类似datetime
,VARCHAR(100)
,int
等
几分钟后内存释放如果我停止重复搜索&绑定活动。
如果数据量相同,为什么内存每次都会增加?
我也试过以下代码,但没有区别。
dataGridView1.DataSource = null;
dataGridView1.DataSource = ds.Tables[0];
我在原始应用程序中使用 Telerik 控件。 Telerik网格比DataGridView消耗更多内存,但DataGridView具有相同的行为。
请记住,此示例只包含一个表单,一个按钮和此表单上的网格。
感谢。
答案 0 :(得分:2)
ds.Dispose()不会做任何事情,因为数据仍然绑定到网格。下次你创建一个新的ds,填充它然后绑定它,旧的ds值不再绑定,但垃圾收集器不一定会立即清理。每次单击时,都会消耗更多内存而不释放任何内存。内存最终会释放,因为当您停止重复搜索和绑定时,GC有机会清除旧的未绑定数据。
虽然每次搜索的数据的大致大小应该相同,但对于新的ds和datagridview,每次通过都是唯一的事件,并且与先前的搜索/绑定的数据没有关联。
我认为,但绝对不确定,GC的设计不会影响性能,也就是说,除非存在严重的内存问题,否则它不应该接管CPU来进行收集。它应该尝试在空闲CPU时间内进行清理。在这种情况下,所有搜索和绑定都会有效地阻止GC。
答案 1 :(得分:1)
DataSet是一个繁重的对象,仅用于从数据库中提取数据。如果你需要有多个表关系等,它只是值得使用。把它想象成可以同步到永久数据库的内存数据库。
一种选择是使用自定义对象和DataReader循环并填充List<yourObject>
。这可能会占用最少的内存。
使其更接近您所拥有的另一个选项是跳过DataSet。尝试这样的事情,看看内存使用是否有所改善:
using (SqlConnection myConnection = new SqlConnection(connectionString))
using (SqlCommand myCommand = new SqlCommand("select * from supplier", myConnection))
{
myConnection.Open();
using (SqlDataReader myReader = myCommand.ExecuteReader())
{
DataTable myTable = new DataTable();
myTable.Load(myReader);
myConnection.Close();
dataGridView1.DataSource = myTable;
}
}
旁注:
目前在您的代码中,如果DataSet ds = new DataSet()
和ds.Dispose()
之间发生异常,则Dispose()
将无法运行。您应该using (DataSet ds = new DataSet()) { ... }
来保证Dispose()
能够运行。然后,您可以删除ds.Dispose()
。