Я сделал 64-битное тестовое приложение WPF. Когда мое приложение работает и открывается диспетчер задач, я просматриваю использование своей системной памяти. Я вижу, что я использую 2 ГБ, и у меня есть 6 ГБ.
В моем приложении я нажимаю кнопку "Добавить", чтобы добавить новый массив байтов размером 1 ГБ в список. Я вижу, что использование моей системной памяти увеличивается на 1 ГБ. Я нажимаю "Добавить" всего 6 раз, заполняя 6 ГБ памяти, которую я имел, когда я начал.
Я нажимаю кнопку "Удалить" 6 раз, чтобы удалить каждый массив из списка. Удаленные байт-массивы не должны ссылаться на какой-либо другой объект в моем элементе управления.
Когда я удаляю, я не вижу, чтобы моя память опускалась. Но все в порядке со мной, потому что я понимаю, что GC не детерминирован и все такое. Я полагаю, что GC будет собираться по мере необходимости.
Итак, теперь, когда память выглядит полной, но ожидая, что GC соберется, когда потребуется, я снова добавлю. Мой компьютер начинает скользить в и из диска, изматывая кому. Почему GC не собирался? Если это не время для этого, когда?
Как проверка работоспособности, у меня есть кнопка для принудительного включения GC. Когда я нажимаю это, я быстро возвращаю 6 ГБ. Разве это не доказывает, что мои 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 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();
}