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