C# Winforms应用程序内存问题-每次搜索和绑定活动内存都会增加

C# Winforms应用程序内存问题-每次搜索和绑定活动内存都会增加,c#,.net,winforms,memory,telerik,C#,.net,Winforms,Memory,Telerik,我的应用程序内存有问题。每次我从数据库中获取数据并将其分配到网格时,内存都会增加,有时进行大量搜索时,内存会达到1G.B 可能还有其他内存处理问题,但为了测试搜索和绑定数据会反复消耗大量内存,我创建了一个新的winforms应用程序,并在其上放置一个按钮和一个网格,然后编写此代码 private void button1_Click(object sender, EventArgs e) { using (SqlConnection con = new SqlConnection(con

我的应用程序内存有问题。每次我从数据库中获取数据并将其分配到网格时,内存都会增加,有时进行大量搜索时,内存会达到1G.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具有相同的行为

请记住,此示例仅由一个表单、一个按钮和表单上的一个网格组成

谢谢。

ds.Dispose()将不起任何作用,因为数据仍然绑定到网格。下一次创建新的ds时,填充它然后绑定它,旧的ds值不再绑定,但垃圾收集器不一定会立即清理。每次单击都会消耗更多内存,而不会释放任何内存。内存最终会释放,因为当您停止重复搜索和绑定时,GC有机会清理旧的未绑定数据

虽然每次搜索的数据的大致大小应该相同,但对于新的ds和datagridview,每次通过都是唯一的事件,并且与先前搜索/绑定的数据没有相关性


我认为,但肯定不确定GC的设计是否不会影响性能,也就是说,除非存在严重的内存问题,否则它不应该接管CPU进行收集。它应该尝试在空闲CPU时间内进行清理。在这种情况下,所有的搜索和绑定都会有效地暂停GC。

数据集是一个沉重的对象,仅用于从数据库中提取数据。只有当您需要多个具有关系等的表时,才值得使用它。请将其视为可以同步到永久数据库的内存中数据库

一个选项是使用自定义对象和数据读取器循环并填充
列表
。这可能会消耗最少的内存

另一个使数据集更接近现有数据集的选项是跳过数据集。尝试以下方法,看看内存使用情况是否有所改善:

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()
将不会运行。您应该使用(DataSet ds=new DataSet()){…}执行
操作,以确保
Dispose()
将运行。然后可以删除
ds.Dispose()

“为什么内存每次都会增加,因为数据量是相同的”-但是数据是不同的。我认为这与数据无关。单击该按钮时,UI设计器将再次使用数据绘制网格。所以内存使用量增加了。您可以尝试从数据库获取数据,但不绑定到网格。这会增加数据吗?UI设计器绘制,这会导致内存使用。是的,但它应该在一定程度上增加内存,然后停止它,但如果我继续单击按钮,它会不断增加内存。代码中有一些错误:ds不应该被处理(但你会侥幸逃脱),adp应该被处理。@cdkMoose给出了更多发生这种情况的原因以及无法避免的原因(GC在需要运行时运行)。我的答案是如何使用更轻量级(开销更小)的对象,以使其运行更快并最大限度地减少内存使用。如果是服务器端代码,它也将更具可伸缩性。