データベースからDatagridview
約 25000 レコードを読み取っています。この読み取り中、アプリケーションは「応答なし」モードになり、プロセス メモリがどんどん大きくなり、2500 ~ 3800 MB あたりで停止することがわかります。を含むフォームを閉じた後Datagridview
、メモリはこのサイズのままです。
私の質問は次のとおりです。
- 大量のデータを読み取っているときに「応答なし」を回避するにはどうすればよいですか?
- データベースから読み取るときに使用されるメモリの量を減らすにはどうすればよいですか (大量のメモリがあるため、何か間違っていると思います)。
- フォームを閉じた後、そのメモリをすべてクリアするにはどうすればよいですか? 私はできる限りすべてを処分していますが、GC がまだメモリを解放していないようです.処分されていないイベントハンドラについて何か読みましたか?
DB から への読み取りのコード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が機能しませんでした)
ありがとうございます。
編集: 3 GB のメモリ リークが発生したとき、データベースには約 500 万のレコードがありました (DB をいっぱいにするスクリプトがあり、それを停止するのを忘れていたため、それに気づきませんでした)。
これで、メモリ リークは許容範囲内になりました。レコードを DataGridView に追加する前よりも約 10 MB 増えています。それでも..仮想モードを使用して、できる限りすべてを閉じる/破棄しようとしても、メモリを埋めるたびに約10 MB増加します。