64 ビット WPF テスト アプリを作成しました。アプリを実行し、タスク マネージャーを開いた状態で、システム メモリの使用状況を監視します。2GB を使用していて、6GB の空き容量があります。
私のアプリでは、[追加] ボタンをクリックして、新しい 1GB バイト配列をリストに追加します。システムのメモリ使用量が 1GB 増加しています。[追加] を合計 6 回クリックし、開始時に使用できた 6 GB のメモリをいっぱいにしました。
[削除] ボタンを 6 回クリックして、リストから各アレイを削除します。削除されたバイト配列は、コントロール内の他のオブジェクトから参照されるべきではありません。
削除しても、メモリが減ることはありません。しかし、GC が非決定論的であることなどを理解しているので、それで問題ありません。必要に応じてGCが収集すると思います。
そのため、メモリがいっぱいに見えますが、必要に応じて GC が収集されることを期待して、もう一度追加します。私の PC は、ディスク スラッシング コマに出入りし始めます。GC が収集しなかったのはなぜですか? その時でなければ、いつですか?
健全性チェックとして、GC を強制するボタンがあります。それを押すと、すぐに 6GB が戻ってきます。それは、私の 6 つの配列が参照されておらず、GC が知っていた/望んでいた場合に収集された可能性があることを証明しませんか?
私は GC.Collect() を呼び出すべきではないということをたくさん読みましたが、この状況で GC が収集されない場合、他に何ができますか?
private ObservableCollection<byte[]> memoryChunks = new ObservableCollection<byte[]>();
public ObservableCollection<byte[]> MemoryChunks
{
get { return this.memoryChunks; }
}
private void AddButton_Click(object sender, RoutedEventArgs e)
{
// Create a 1 gig chunk of memory and add it to the collection.
// It should not be garbage collected as long as it's in the collection.
try
{
byte[] chunk = new byte[1024*1024*1024];
// Looks like I need to populate memory otherwise it doesn't show up in task manager
for (int i = 0; i < chunk.Length; i++)
{
chunk[i] = 100;
}
this.memoryChunks.Add(chunk);
}
catch (Exception ex)
{
MessageBox.Show(string.Format("Could not create another chunk: {0}{1}", Environment.NewLine, ex.ToString()));
}
}
private void RemoveButton_Click(object sender, RoutedEventArgs e)
{
// By removing the chunk from the collection,
// I except no object has a reference to it,
// so it should be garbage collectable.
if (memoryChunks.Count > 0)
{
memoryChunks.RemoveAt(0);
}
}
private void GCButton_Click(object sender, RoutedEventArgs e)
{
GC.Collect();
GC.WaitForPendingFinalizers();
}