1

私のコードは多くの辞書を使用しており、それらすべてからメモリを解放する際に問題が発生しています。この回答で学んだことを使用して調査すると、 GenericEqualityComparer がそこにあることがわかり、それがこのメモリを使用し続けていると思われます。

誰でもこれを確認できますか、またはこのメモリを解放する方法を教えてください。

コード

        Console.WriteLine("{0,10}: Start Point", GC.GetTotalMemory(true));
        List<string> t1 = new List<string>();
        Console.WriteLine("{0,10}: <------- Create List", GC.GetTotalMemory(true));
        t1 = null;
        Console.WriteLine("{0,10}: <------- null List", GC.GetTotalMemory(true));

        GC.Collect();
        Console.WriteLine("{0,10}: After GC.Collect", GC.GetTotalMemory(true));
        Dictionary<string, string> t2 = new Dictionary<string, string>();
        Console.WriteLine("{0,10}: <------- Create Dict", GC.GetTotalMemory(true));
        t2 = null;
        Console.WriteLine("{0,10}: <------- null Dict", GC.GetTotalMemory(true));


        GC.Collect();
        Console.WriteLine("{0,10}: After GC.Collect", GC.GetTotalMemory(true));
        Dictionary<string, string> t3 = new Dictionary<string, string>();
        Console.WriteLine("{0,10}: <------- Create Dict", GC.GetTotalMemory(true));
        t3 = null;
        Console.WriteLine("{0,10}: <------- null Dict", GC.GetTotalMemory(true));

        GC.Collect();
        Console.WriteLine("{0,10}: After GC.Collect", GC.GetTotalMemory(true));
        Dictionary<string, string> t4 = new Dictionary<string, string>();
        Console.WriteLine("{0,10}: <------- Create Dict", GC.GetTotalMemory(true));
        t4 = null;
        Console.WriteLine("{0,10}: <------- null Dict", GC.GetTotalMemory(true));

        GC.Collect();
        Console.WriteLine("{0,10}: After GC.Collect", GC.GetTotalMemory(true));
        Dictionary<string, string> t5 = new Dictionary<string, string>();
        Console.WriteLine("{0,10}: <------- Create Dict", GC.GetTotalMemory(true));
        t5 = null;
        Console.WriteLine("{0,10}: <------- null Dict", GC.GetTotalMemory(true));

        GC.Collect();
        Console.WriteLine("{0,10}: After GC.Collect", GC.GetTotalMemory(true));
        Dictionary<string, string> t6 = new Dictionary<string, string>();
        Console.WriteLine("{0,10}: <------- Create Dict", GC.GetTotalMemory(true));
        GC.KeepAlive(t6);
        t6 = null;
        Console.WriteLine("{0,10}: <------- null Dict", GC.GetTotalMemory(true));

        GC.Collect();
        Console.WriteLine("{0,10}: <------- End.", GC.GetTotalMemory(true));

注: このコードには 2 つのバージョンがあります。SO でここで提案されたように GC.Collect を使用した 1 つの編集ですが、それは何のメリットもありません。

GC コレクションなしの出力

 95884: Start Point
 97872: <------- Create List
 97888: <------- null List
 97952: <------- Create Dict
 97968: <------- null Dict
 98032: <------- Create Dict
 98048: <------- null Dict
 98112: <------- Create Dict
 98128: <------- null Dict
 98192: <------- Create Dict
 98208: <------- null Dict
 98272: <------- Create Dict
 98288: <------- null Dict

GC コレクションを使用した出力 (提案ごと)

 96004: Start Point
 97992: <------- Create List
 98008: <------- null List
 98024: After GC.Collect
 98088: <------- Create Dict
 98104: <------- null Dict
 98120: After GC.Collect
 98184: <------- Create Dict
 98200: <------- null Dict
 98216: After GC.Collect
 98280: <------- Create Dict
 98296: <------- null Dict
 98312: After GC.Collect
 98376: <------- Create Dict
 98392: <------- null Dict
 98408: After GC.Collect
 98472: <------- Create Dict
 98488: <------- null Dict
 98504: <------- End.

リリースモードでの出力 (提案による)

 96028: Start Point
 98016: <------- Create List
 98032: <------- null List
 98048: After GC.Collect
 98112: <------- Create Dict
 98128: <------- null Dict
 98144: After GC.Collect
 98208: <------- Create Dict
 98224: <------- null Dict
 98240: After GC.Collect
 98304: <------- Create Dict
 98320: <------- null Dict
 98336: After GC.Collect
 98400: <------- Create Dict
 98416: <------- null Dict
 98432: After GC.Collect
 98496: <------- Create Dict
 98512: <------- null Dict
 98528: <------- End.

GC Collect なしの Release モードでの出力 (提案による)

 96028: Start Point
 98016: <------- Create List
 98032: <------- null List
 98096: <------- Create Dict
 98112: <------- null Dict
 98176: <------- Create Dict
 98192: <------- null Dict
 98256: <------- Create Dict
 98272: <------- null Dict
 98336: <------- Create Dict
 98352: <------- null Dict
 98416: <------- Create Dict
 98432: <------- null Dict
 98448: <------- End.
4

3 に答える 3

2

デバッグ モードでは、GCは現在のメソッド スコープ内のオブジェクトを収集しません。オブジェクトへの参照がまだ存在するためです。リリース用にビルドし、デバッグせずに実行して結果を確認してください。

デバッグ モードでは true を出力し、リリースでは false を出力するコード:

object obj = new object();
WeakReference reference = new WeakReference(obj);
GC.Collect(0, GCCollectionMode.Forced);
Console.WriteLine(reference.IsAlive);

OP からの編集: デバッグ モードでは、メモリ使用量が人為的に増加しました。スタンドアロン アプリを実行すると、この出力が得られました。ありがとう、そして私はこの答えを受け入れています。

 21852: Start Point
 29328: <------- Create List
 29328: <------- null List
 29328: <------- Create Dict
 29328: <------- null Dict
 29328: <------- Create Dict
 29328: <------- null Dict
 29328: <------- Create Dict
 29328: <------- null Dict
 29328: <------- Create Dict
 29328: <------- null Dict
 29376: <------- Create Dict
 29328: <------- null Dict
 29328: <------- End.
于 2012-10-20T13:34:40.440 に答える
0

まあ、あなたはメモリを解放していません

value = null;

メモリから何かを削除するのではなく、値を null に設定するだけです。ガベージ コレクターは、タスクの実行を明示的に要求されません。

GC.Collect();

そのタスクを実行するために必要なものです。GC は適切に記述されており、未使用のオブジェクトの収集を独自の時間に行うため、通常はそうしません。また、理由もなく頻繁に呼び出すと、パフォーマンスに大きな影響を与える可能性があります。GC が何かを収集する方法と理由に関する条件のコレクションもあります。デバッグ、メソッド、スコープなど。

于 2012-10-20T13:35:09.207 に答える
0

のドキュメントからGC.GetTotalMemory

forceFullCollection パラメーターが true の場合、このメソッドは、システムがガベージを収集してオブジェクトをファイナライズする間、戻る前に短い間隔で待機します。間隔の長さは、完了したガベージ コレクション サイクルの数と、サイクル間で回復されるメモリ量の変化によって決定される、内部的に指定された制限です。ガベージ コレクターは、アクセスできないすべてのメモリが収集されることを保証しません。

したがって、バグはありません。GC は非決定論的であり、GetTotalMemory(true) がすべてをクリーンアップすることに依存することはできません。

GC.Collect()フルガベージコレクションを行うには、電話する必要があります。

于 2012-10-20T13:35:21.750 に答える