Тип System.GC

47

В библиотеках базовых классов доступен класс по имени System.GC, который позволяет программно взаимодействовать со сборщиком мусора за счет обращения к его статическим членам. Необходимость в непосредственном использовании этого класса в разрабатываемом коде возникает крайне редко (а то и вообще никогда). Обычно единственным случаем, когда нужно применять члены System.GC. является создание классов, предусматривающих использование на внутреннем уровне неуправляемых ресурсов. Это может быть, например, класс, работающий с основанным на С интерфейсом Windows API за счет применения протокола вызовов платформы .NET, или какая-то низкоуровневая и сложная логика взаимодействия с СОМ.

В .NET 3.5 с пакетом обновлений Service Pack 1 появилась дополнительная возможность получать уведомления перед началом процесса сборки мусора за счет применения ряда новых членов. И хотя данная возможность может оказаться полезной в некоторых сценариях, в большинстве приложений она не нужна, поэтому здесь подробно не рассматривается. Всю необходимую информацию об уведомлениях подобного рода можно найти в разделе "Garbage Collection Notifications" ("Уведомления о сборке мусора") документации .NET Framework 4.0 SDK.

В следующей таблице приведено краткое описание некоторых наиболее интересных членов класса System.GC:

Члены класса System.GC
Метод Описание
AddMemoryPressure(),
RemoveMemoryPressure()
Позволяют указывать числовое значение, отражающее "уровень срочности", который вызывающий объект применяет в отношении к сборке мусора. Следует иметь в виду, что эти методы должны изменять уровень давления в тандеме и, следовательно, никогда не устранять больше давления, чем было добавлено
CancelFullGCNotification() Отменяет уведомление о "сборке мусора"
Collect() Заставляет сборщик мусора провести сборку мусора. Должен быть перегружен так, чтобы указывать, объекты какого поколения подлежат сборке, а также какой режим сборки использовать (с помощью перечисления GCCollectionMode)
CollectionCount() Возвращает числовое значение, показывающее, сколько раз объектам данного поколения удалось переживать процесс сборки мусора
GetGeneration() Возвращает информацию о том, к какому поколению в настоящий момент относится объект
GetTotalMemory() Возвращает информацию о том, какой объем памяти (в байтах) в настоящий момент занят в управляемой куче. Булевский параметр указывает, должен ли вызов сначала дождаться выполнения сборки мусора, прежде чем возвращать результат
KeepAlive() Создает ссылку на объект, защищая его от "сборки мусора". Действие этой ссылки оканчивается после выполнения метода KeepAlive()
MaxGeneration Возвращает информацию о том, сколько максимум поколений поддерживается в целевой системе. В .NET 4.0 поддерживается всего три поколения: 0, 1 и 2
RegisterForFullGCNotification() Разрешает уведомление о "сборке мусора".
RemoveMemoryPressure() Задает в качестве параметра количество байтов, освобождаемых в неуправляемой области памяти
SuppressFinalize() Позволяет устанавливать флаг, указывающий, что для данного объекта не должен вызываться его метод Finalize()
WaitForPendingFinalizers() Позволяет приостанавливать выполнение текущего потока до тех пор, пока не будут финализированы все объекты, предусматривающие финализацию. Обычно вызывается сразу же после вызова метода GC.Collect()

Для проектов с неуправляемым кодом особое значение имеют два следующих метода из класса GC: AddMemoryPressure() и RemoveMemoryPressure(). С их помощью указывается большой объем неуправляемой памяти, выделяемой или освобождаемой в программе.

Особое значение этих методов состоит в том, что система управления памятью не контролирует область неуправляемой памяти. Если программа выделяет большой объем неуправляемой памяти, то это может сказаться на производительности, поскольку системе ничего неизвестно о таком сокращении объема свободно доступной памяти. Если же большой объем неуправляемой памяти выделяется с помощью метода AddMemoryPressure(), то система CLR уведомляется о сокращении объема свободно доступной памяти. А если выделенная область памяти освобождается с помощью метода RemoveMemoryPressure(), то система CLR уведомляется о соответствующем восстановлении объема свободно доступной памяти. Следует, однако, иметь в виду, что метод RemoveMemoryPressure() необходимо вызывать только для уведомления об освобождении области неуправляемой памяти, выделенной с помощью метода AddMemoryPressure().

Давайте рассмотрим пример:

using System;

namespace ConsoleApplication1
{
    class UserInfo
    {
        public string Name { set; get; }
        public int Age { set; get; }

        public UserInfo(string Name, int Age)
        {
            this.Name = Name;
            this.Age = Age;
        }
    }

    class Program
    {
        static void Main()
        {
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine("БАЗОВАЯ ИНФОРМАЦИЯ О СИСТЕМЕ: \n" + 
                "-----------------------------\n");
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine(@"Операционная система: {0}
Версия .NET Framework: {1}",Environment.OSVersion,Environment.Version);
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine("\nИНФОРМАЦИЯ О СБОРКЕ МУСОРА: \n" +
                "---------------------------\n");
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine(@"Количество байт в куче: {0}
Максимальное количество поддерживаемых поколений объектов: {1}"
                ,GC.GetTotalMemory(false),GC.MaxGeneration+1);

            UserInfo user1 = new UserInfo("Alex", 26);
            Console.WriteLine("Поколение объекта user1: " + GC.GetGeneration(user1));

            for (int i = 0; i < 50000; i++)
            {
                UserInfo user = new UserInfo("Dm",27);
            }

            // Намеренно вызовем сборку мусора
            GC.Collect(0, GCCollectionMode.Forced);
            GC.WaitForPendingFinalizers();
            Console.WriteLine("\nсборка мусора ...\n");

            Console.WriteLine("Теперь поколение объекта user1: " +GC.GetGeneration(user1));

            Console.ReadLine();
        }
    }
}
Управление сборкой мусора

Сборщик мусора .NET предназначен в основном для того, чтобы управлять памятью вместо разработчиков. Однако в очень редких случаях требуется принудительно запустить сборку мусора с помощью метода GC.Collect(). Примеры таких ситуаций приведены ниже:

Пройди тесты
Лучший чат для C# программистов