2013-01-13 36 views
1

我从数据库中读取到我的Datagridview约25000条记录。 在此阅读,应用是在“没有响应”的模式,我可以看到它的进程内存越来越大,并停止围绕2500-3800 MB。 后,我关闭包含Datagridview形式,内存保持在这个规模。如何减少和如何清除内存泄漏?

我的问题是:

  1. 如何避免“没有响应”当我读了巨大的数据量?
  2. 如何减少我从数据库中读取时正在使用的内存量(我认为我做错了什么,因为它有很多内存)
  3. 如何清除I后的所有内存关闭表格?我正在处理所有我能做的事情,但似乎GC仍然没有释放内存..我读了一些关于事件处理程序的信息,这些信息并不是被处置的?

从数据库读取的代码到Datagridview

delegate void SetSearchCallback(); 
public void Search() 
{ 
    sqlCommand=""; 
    if (this._dbReports.InvokeRequired) 
    { 
     SetSearchCallback d = new SetSearchCallback(Search); 
     this.Invoke(d, new object[] { }); 
    } 
    else 
    { 
      DateTime startDate = new DateTime(dateTimePicker1.Value.Year, dateTimePicker1.Value.Month, dateTimePicker1.Value.Day); 
      DateTime endDate = new DateTime(dateTimePicker2.Value.Year, dateTimePicker2.Value.Month, dateTimePicker2.Value.Day); 
      sqlCommand = "select * FROM cstPackages where _dateTime >= '" + String.Format("{0:yyyy-MM-dd}", startDate) + "' and _dateTime <='" + String.Format("{0:yyyy-MM-dd} 23:59:59.999", endDate) + "' order by _dateTime desc"; //reading the db from end to start 
    } 

     if (sqlCommand != "") 
     { 
      using (SqlConnection sCon2 = new SqlConnection("Data Source=" + SettingsForm.getAddress + ";Initial Catalog=" + SettingsForm.getDatabase + ";Integrated Security=False;User Id=" + SettingsForm.getUser + ";Password=" + SettingsForm.getPassword + ";Connect Timeout=5;")) 
      { 
       try 
       { 
        sCon2.Open(); 
        using (da = new SqlDataAdapter(sqlCommand, sCon2)) 
        { 
         dsReport.Clear(); 
         da.Fill(dsReport, "cstPackages"); 
         dbBind = new BindingSource(dsReport, "cstPackages"); 
         if (firstTime == 0) 
          _dbReports.Columns.Clear(); 

         _dbReports.DataSource = dbBind; 

         if (firstTime == 0) 
         { 
          updateDataGridSettings(); 
          firstTime = 1; 
         } 

         _dbReports.Refresh(); 
         sCon2.Close(); 
         sCon2.Dispose(); 
        } 
       } 
       catch (Exception c) 
       { 
        fn.errorHandler(c.Message, SettingsForm); 
       } 
      } 
     } 
    } 
} 

,当我关闭窗体:(btnPress=1只有当我充满了Datagridview的东西)

private void Reports_FormClosing(object sender, FormClosingEventArgs e) 
{ 
    _dbReports.Dispose(); 
    if (btnPress == 1) 
    { 
     dsReport.Dispose(); 
     da.Dispose(); 
     dbBind.Dispose(); 
    } 
} 

而在窗体关闭后的父窗体中,我打电话给ReportForm.Dispose();

我知道Dispose没有清除内存,但它应该有助于GC完成它的工作,对吧?

昨晚我离开了应用通宵营业(我关上了ReportForm后),并在上午的记忆是相同的(在GC没有工作)

在先进的感谢。

编辑: 当我拿到3GB内存泄漏,我的数据库是约5万条记录(我没有注意到,因为我有被灌我的数据库的脚本,我忘了停下来)

现在内存泄漏是比较可以接受的,这是大约10 MB超过它以前我添加记录到DataGridView。 不过。即使当我使用虚拟模式,并试图关闭/处置尽我所能,每个填充内存生长在大约10 MB。

+2

你在TaskManager中看到的与GC没有直接关系(做或不做)。除了在GUI中加载25k记录不明智之外,这里没有直接指示问题。 –

+0

25K是可能的最大数量,它应该在2K左右,但我想让应用程序达到极限并寻找错误。 那么为什么当我用'Datagridview'关闭winform时,计算机没有清除内存? – Itay

+0

你需要同时显示所有这些行吗?您的DataGridView是否处于虚拟模式?你的记忆问题何时出现?从数据库加载或设置DataGridView的DataSource时? –

回答

1

1)如何在阅读海量数据时避免“不响应”?

通过一个单独的线程做这个昂贵的任务。在WinForms中,BackgroundWorker非常有用,因为它在作业完成后自动将调用集成到主UI线程。

2)如何减少的内存量,当我从 数据库读取正在使用(我认为我做错了什么,becude这是一个 大量的内存)

您可以尝试启用Virtual Mode并开始分页数据。一次加载25000条记录是无用的。无论如何,用户将永远无法与他们一起工作。

3)如何在关闭表格后清除所有内存?我正在处理 所能做的一切,但似乎GC仍然没有释放内存..我读了一些关于不是 的事件处理程序?

一旦您关闭表单,垃圾收集器将负责处理所有资源。只要确保你从不存储任何对它的引用,以便它符合GC的条件。

+0

谢谢。 我会立即检查它。我关闭并处理了我所能做的一切,但是在关闭表单后内存仍然很大。有什么办法可以强制关闭所有的引用吗? – Itay

+0

是的,确保没有任何参考指向这个表单了。你也可以尝试调用'GC.Collect()'立即运行垃圾收集器。但请注意,这通常是不好的做法,因为GC知道什么时候最适合运行而不会在应用程序中产生任何争用。 –