Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
С# и объектно-ориентированное программирование.doc
Скачиваний:
5
Добавлен:
01.05.2025
Размер:
1 Мб
Скачать
    1. Принудительная активизация сборки мусора

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

Примеры таких ситуацийприведены ниже.

  • Приложение приступает к выполнению блока кода, прерывание которого возможным процессом сборки мусора является недопустимым.

  • Приложение только что закончило размещать чрезвычайно большое количество объектов и нуждается в как можно скорейшем освобождении большого объема памяти.

Если выяснилось, что выполнение сборщиком мусора проверки на предмет наличия недостижимых объектов может быть выгодным, можно инициировать процесс сборки мусора явным образом, как показано ниже:

static void Main(string [ ] args)

{

// Принудительная активизация процесса сборки мусора и

// ожидание завершения финализации каждого из объектов.

GC.Collect ();

GC.WaitForPendingFinalizers ();

}

static void Main(string [ ] args)

{

// Принудительная активизация процесса сборки мусора и

// ожидание завершения финализации каждого из объектов.

GC.Collect ();

GC.WaitForPendingFinalizers ();

}

В случае принудительной активизации сборки мусора не забывайте вызвать метод GC.WaitForPendingFinalizers(). Это дает возможность всем финализируемым объектам произвести любую необходимую очистку перед продолжением работы программы. Метод GC.WaitForPendingFinalizers() незаметно приостанавливает выполнение вызывающего "потока" во время процесса сборки мусора, что очень хорошо, поскольку исключает вероятность вызова в коде каких-либо методов на объекте, который в текущий момент уничтожается.

Методу GC.Collect() можно передать числовое значение, отражающее старейшее поколение объектов, в отношении которого должен проводиться процесс сборки мусора. Например, чтобы CLR-среда анализировала только объекты поколения 0, необходимо использовать следующий код:

static void Main(string [ ] args)

{

// Исследование только объектов поколения 0

GC.Collect(0);

GC.WaitForPendingFinalizers();

}

Вдобавок методу Collect() во втором параметре может передаваться значение перечисления GCCollectionMode, которое позволяет более точно указать, каким образом исполняющая среда должна принудительно инициировать сборку мусора. Ниже показаны значения, доступные в этом перечислении:

public enum GCCollectionMode

{

Default, // Текущим значением по умолчанию является Forced.

Forced, // Указывает исполняющей среде начать сборку мусора немедленно1

Optimized // Позволяет исполняющей среде выяснить, оптимален

//ли настоящий момент для удаления объектов.

}

Как и при любой сборке мусора, в случае вызова GC.Collect() уцелевшим объектам назначается статус объектов более высокого поколения. Чтобы удостовериться в этом, модифицируем метод Main() следующим образом:

static void Main(string[] args)

{

// Отображение примерного количества байтов в куче.

Console.WriteLine("Estimated bytes on heap: {0}",

GC.GetTotalMemory(false));

// Отсчет значения MaxGeneration начинается с нуля.

Console.WriteLine("This OS has {0} object generations.\n",

(GC.MaxGeneration + 1) ) ;

Car refToMyCar = new Car("Zippy", 100);

Console.WriteLine(refToMyCar.ToString());

// Вывод информации о поколении, к которому

// относится refToMyCar.

Console.WriteLine ("\nGeneration of refToMyCar is: {0}",

GC.GetGeneration(refToMyCar));

// Создание большого количества объектов для целей тестирования.

object[] tonsOfObjects = new object[50000];

for (int i = 0; i < 50000; i++)

tonsOfObjects [i] = new object ();

// Выполнение сборки мусора в отношении только

// объектов, относящихся к поколению 0.

GC.Collect @, GCCollectionMode.Forced);

GC.WaitForPendingFinalizers();

// Вывод информации о поколении, к которому

// относится refToMyCar.

Console.WriteLine("\nGeneration of refToMyCar is: {0}",

GC.GetGeneration(refToMyCar));

// Выполнение проверки, удалось ли

// tonsOfObjects[9000] уцелеть после сборки мусора.

if (tonsOfObjects[9000] !=null)

{

// Вывод поколения tonsOfObjects [ 9000]

Console.WriteLine("Generation of tonsOfObjects[9000] is: {0}",

GC.GetGeneration(tonsOfObjects [ 9000]));

}

else

// tonsOfObjects[9000] больше не существует.

Console.WriteLine("tonsOfObjects[9000] is no longer alive.");

// Вывод информации о том, сколько раз в отношении

// объектов каждого поколения выполнялась сборка мусора.

Console.WriteLine("\nGen 0 has been swept {0} times",

GC.CollectionCount@));

Console.WriteLine("Gen 1 has been swept {0} times",

GC.CollectionCountA));

Console.WriteLine("Gen 2 has been swept {0} times",

GC.CollectionCountB));

Console.ReadLine();

}

Дя целей тестирования был создан очень большой массив типа object (состоящий из 50000 элементов). Как можно увидеть по приведенному ниже выводу, хотя в данном методе Main() и был сделан только один явный запрос на выполнение сборки мусора (с помощью метода GC.Collect()), среда CLR в фоновом режиме провела несколько таких сборок.

Результаты работы программы (вывод на консоль):

Estimated bytes on heap: 70240

This OS has 3 object generations.

Zippy is going 100 MPH

Generation of refToMyCar is: 0

Generation of refToMyCar is: 1

Generation of tonsOfObjects [ 9000] is: 1

Gen 0 has been swept 1 times

Gen 1 has been swept 0 times

Gen 2 has been swept 0 times