Тип System.GC
47C# --- Руководство по C# --- Тип System.GC
В библиотеках базовых классов доступен класс по имени System.GC, который позволяет программно взаимодействовать со сборщиком мусора за счет обращения к его статическим членам. Необходимость в непосредственном использовании этого класса в разрабатываемом коде возникает крайне редко (а то и вообще никогда). Обычно единственным случаем, когда нужно применять члены System.GC. является создание классов, предусматривающих использование на внутреннем уровне неуправляемых ресурсов. Это может быть, например, класс, работающий с основанным на С интерфейсом Windows API за счет применения протокола вызовов платформы .NET, или какая-то низкоуровневая и сложная логика взаимодействия с СОМ.
В .NET 3.5 с пакетом обновлений Service Pack 1 появилась дополнительная возможность получать уведомления перед началом процесса сборки мусора за счет применения ряда новых членов. И хотя данная возможность может оказаться полезной в некоторых сценариях, в большинстве приложений она не нужна, поэтому здесь подробно не рассматривается. Всю необходимую информацию об уведомлениях подобного рода можно найти в разделе "Garbage Collection Notifications" ("Уведомления о сборке мусора") документации .NET Framework 4.0 SDK.
В следующей таблице приведено краткое описание некоторых наиболее интересных членов класса 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(). Примеры таких ситуаций приведены ниже:
Приложение приступает к выполнению блока кода, прерывание которого возможным процессом сборки мусора является недопустимым.
Приложение только что закончило размещать чрезвычайно большое количество объектов и нуждается в как можно скорейшем освобождении большого объема памяти.