2

概念を理解していないか、間違ったことをしている可能性があります。.NET でのメモリ管理についていくつか質問があります。

状況を想像してください:

Form1MDI-parent と little のように、big man Form はFormChild子としてバインドされます。

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void simpleButton1_Click(object sender, EventArgs e)
        {
            FormChild formChild = new FormChild();

            formChild.MdiParent = this;
            formChild.Show();

        }
    }

ここで、子はシミュレーションとして少しメモリを割り当てています。

public partial class FormChild : Form
{
    private readonly List<byte[]> _list = new List<byte[]>();

    public FormChild()
    {
        InitializeComponent();


    }

    private void FormChild_Load(object sender, EventArgs e)
    {
        int i = 0;
        while (i < 100)
        {
            _list.Add(new byte[1024 * 1024 * 10]);
            i += 1;
        }

    }

}

現在、メモリ ヒープで何が起こっているかをメモリ プロファイラーで調べています。ボタンをクリックすると、メモリが割り当てられます。次に、を閉じるFormChildと、が呼び出されますDispose()。しかし、メモリはまだ割り当てられています。もう一度クリックすると、発生しSystem.OutOfMemoryExceptionます。

GC がマネージド メモリの解放を待機しているのはなぜですか? それとも私の設計ミスですか?

4

4 に答える 4

6

GC は、メモリ不足に応じてメモリを解放するだけです。Dispose の主な目的は、メモリに関連しないリソースをクリーンアップすることです。

つまり、管理対象オブジェクトを無効にしても、必ずしも収集が速くなるわけではありませんが、メモリの問題の診断がはるかに簡単になります。

于 2012-09-18T17:40:31.770 に答える
3

formChild の最初のインスタンスがまだ到達可能 (つまり、ガベージではない) で、2 番目のインスタンスが作成されるという、ある種のタイミングの問題のように見えます。2度と対応できません_list

FormChild を閉じると、Dispose() が呼び出されることに注意してください。これは、リソースとウィンドウ ハンドルに関するステートメントであり、メモリの解放に関するステートメントではありません。

独自の Dispose() を作成したかどうかは明確ではありませんが、この (かなり特殊な) ケースでは作成する必要があります。

  • void Dispose(bool disposing)メソッドをFormChild.Designer.csファイルから切り取り、に移動しFormChild.csます。

  • それを使用して、巨大なメモリ ブロックを解放します。

    protected override void Dispose(bool disposing)
    {
        _list = null;  // add this
    
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }
    

これはメモリ管理の「通常の」形式ではないことに注意してください。ただし、_list も珍しいため必要です。

于 2012-09-18T18:40:24.823 に答える
0

GC.Collect ( http://msdn.microsoft.com/en-us/library/xe0c2357.aspx )を使用して、ガベージ コレクションをすぐに実行できます。

ただし、私は通常、それ自体を処理させ、Dispose メソッドを実装します。

于 2012-09-18T18:03:42.640 に答える
-1

リソースをクリアできるようにオーバーライドDisposeします。FormChild

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        if (_list != null)
        {
            // Clear it, dispose it, do whatever you want with it.
        }
    }

    base.Dispose(disposing);
}

Yaur が言ったように、GC がDispose呼び出されたときにすぐにメモリをクリーンアップするわけではありませんが、可能な限りクリーンアップすることをお勧めします。

于 2012-09-18T17:44:20.570 に答える