Сборка мусора не происходит, даже когда это необходимо

Я создал 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();
    }
25
задан Buzz 4 April 2012 в 17:47
поделиться