2

データベースからDatagridview約 25000 レコードを読み取っています。この読み取り中、アプリケーションは「応答なし」モードになり、プロセス メモリがどんどん大きくなり、2500 ~ 3800 MB あたりで停止することがわかります。を含むフォームを閉じた後Datagridview、メモリはこのサイズのままです。

私の質問は次のとおりです。

  1. 大量のデータを読み取っているときに「応答なし」を回避するにはどうすればよいですか?
  2. データベースから読み取るときに使用されるメモリの量を減らすにはどうすればよいですか (大量のメモリがあるため、何か間違っていると思います)。
  3. フォームを閉じた後、そのメモリをすべてクリアするにはどうすればよいですか? 私はできる限りすべてを処分していますが、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増加します。

4

2 に答える 2

2

1)大量のデータを読んでいるときに「応答しない」を回避するにはどうすればよいですか?

この高価なタスクを別のスレッドで実行する。WinFormsでは、BackgroundWorkerジョブが終了するとメインUIスレッドへの呼び出しを自動的にマーシャリングするため、非常に便利です。

2)データベースから読み取るときに使用されるメモリの量を減らすにはどうすればよいですか(メモリが多いため、何か間違ったことをしていると思います)

有効Virtual Modeにして、データのページ付けを開始してみてください。一度に25000レコードをロードするのはかなり無意味です。とにかく、ユーザーは一度にそれらを操作することはできません。

3)フォームを閉じた後、そのメモリをすべてクリアするにはどうすればよいですか?できる限りの処理を行っていますが、GCがまだメモリを解放していないようです。処理されていないイベントハンドラーについて何か読んだことがありますか?

フォームを閉じると、ガベージコレクターがすべてのリソースを破棄します。GCの対象となるように、参照を保存しないように注意してください。

于 2013-01-13T14:12:39.497 に答える