次のコードは、私が見ている問題の簡単な例です。このアプリケーションは、ディクショナリが大きすぎるため、例外をスローする前に約 4 GB のメモリを消費します。
class Program
{
static void Main(string[] args)
{
Program program = new Program();
while(true)
{
program.Method();
Console.ReadLine();
}
}
public void Method()
{
WasteOfMemory memory = new WasteOfMemory();
Task tast = new Task(memory.WasteMemory);
tast.Start();
}
}
public class WasteOfMemory
{
public void WasteMemory()
{
Dictionary<string, string> aMassiveList = new Dictionary<string, string>();
try
{
long i = 0;
while (true)
{
aMassiveList.Add(i.ToString(), "I am a line of text designed to waste space.... I am exceptionally useful........");
i++;
}
}
catch(Exception e)
{
Console.WriteLine("I have broken myself");
}
}
}
これはすべて予想どおりですが、現時点で解決できないのは、このメモリを CLR からいつ解放する必要があるかということです。
タスクを完了させ、メモリ過負荷の状況をシミュレートしましたが、ディクショナリによって消費されたメモリは解放されません。OS のメモリが不足しているため、CLR にメモリを解放する圧力がかかっていませんか?
しかし、さらにややこしいのは、タスクが完了するまで待ってから Enter キーを押してタスクを再度実行すると、メモリが解放されるため、明らかに前の辞書がガベージ コレクションされていることです (そうではありませんか?)。
では、なぜメモリが解放されないのでしょうか。CLR にメモリを解放させるにはどうすればよいでしょうか。
説明や解決策をいただければ幸いです。
編集: 次の返信、特に Beska の返信、問題の私の説明が最も明確ではないことは明らかなので、明確にしようと思います。
コードは最良の例ではないかもしれません。申し訳ありません! 問題を再現しようとするのは、簡単で大雑把なコードでした。
ここでディクショナリを使用して、大規模なカスタム データ オブジェクトがあり、メモリの大部分を占有し、タスクの完了後に解放されないという事実を再現します。
この例では、ディクショナリはディクショナリの制限までいっぱいになり、例外をスローします。永久にいっぱいになるわけではありません! これはメモリがいっぱいになるかなり前のことであり、OutOfMemoryException は発生しません。したがって、結果はメモリ内の大きなオブジェクトになり、タスクは完了します。
この時点で、タスクとメソッド「メソッド」の両方が完了しているため、ディクショナリは範囲外であることが予想されます。したがって、ディクショナリがガベージ コレクションされ、メモリが再利用されることが期待されます。実際には、「メソッド」が再度呼び出されて新しい WasteOfMemory インスタンスが作成され、新しいタスクが開始されるまで、メモリは解放されません。
うまくいけば、それは問題を少し明確にするでしょう