Выпуск ресурсов в .Net C # - PullRequest
13 голосов
/ 04 мая 2010

Я новичок в C # и .NET, и уже читал об этом.

Мне нужно знать, почему и когда мне нужно высвобождать ресурсы? Разве сборщик мусора не заботится обо всем? Когда мне нужно реализовать IDisposable и чем он отличается от деструктора в C ++?

Кроме того, если моя программа довольно мала, например, хранитель экрана, нужно ли мне заботиться об освобождении ресурсов?

Спасибо.

Ответы [ 6 ]

15 голосов
/ 04 мая 2010

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

Теперь сравните это с дескрипторами файлов. Операционная система может иметь достаточно места для выделения большего количества дескрипторов файлов, но если вы оставите дескриптор открытым для определенного файла, никто другой не сможет открыть этот конкретный файл для записи. Вы должны сообщить системе, когда закончите с дескриптором, обычно закрывая соответствующий поток, как только закончите, и сделайте так, чтобы он закрывался, даже если выдается исключение. Обычно это делается с помощью оператора using, который похож на попытку / finally с вызовом Dispose в блоке finally.

Деструкторы в C ++ очень отличаются от финализаторов .NET, поскольку деструкторы C ++ являются детерминированными - они автоматически вызываются, например, когда соответствующая переменная выходит из области видимости. Финализаторы запускаются сборщиком мусора в некоторый момент после того, как на объект больше не ссылаются какие-либо "живые" объекты, но время непредсказуемо. (В некоторых редких случаях это может никогда не произойти.)

Вы должны реализовать IDisposable самостоятельно, если у вас есть какая-либо очистка, которая должна быть сделана детерминистически - обычно это происходит, если одна из переменных вашего экземпляра также реализует IDisposable. В наши дни довольно редко приходится реализовывать финализатор самостоятельно - он обычно нужен только в том случае, если вы держите direct на дескрипторах операционной системы, обычно в виде IntPtr; SafeHandle делает все это намного проще и освобождает вас от необходимости писать финализатор самостоятельно.

2 голосов
/ 04 мая 2010

По сути, вам нужно беспокоиться о выделении ресурсов для неуправляемого кода - всего, что выходит за рамки .NET. Например, соединение с базой данных или файл в ОС.

Сборщик мусора работает с управляемым кодом - кодом в .NET Framework.

Даже небольшому приложению может потребоваться освободить неуправляемые ресурсы, например, оно может записать в локальный текстовый файл. Когда вы закончили с ресурсом, вам нужно убедиться, что вызывается метод Dispose объекта. Оператор с использованием упрощает синтаксис:

using (TextWriter w = File.CreateText("test.txt"))
{
    w.WriteLine("Test Line 1");
}

Объект TextWriter реализует интерфейс IDisposable, поэтому, как только завершается использование блока, вызывается метод Dispose, и объект можно собирать мусором. Фактическое время сбора не может быть гарантировано.

Если вы создаете свои собственные классы, которые необходимо правильно утилизировать, вам нужно будет реализовать интерфейс IDisposable и шаблон Dispose самостоятельно. В простом приложении вам, вероятно, не понадобится делать это, если вы сделаете , это хороший ресурс.

2 голосов
/ 04 мая 2010

Ресурсы бывают двух видов - управляемые и неуправляемые. Управляемые ресурсы будут очищены сборщиком мусора, если вы позволите это, то есть если вы отпустите любую ссылку на объект. Однако сборщик мусора не знает, как освобождать неуправляемые ресурсы, которые содержит управляемый объект - например, файловые дескрипторы и другие ресурсы ОС.

IDisposable рекомендуется, когда есть управляемый ресурс, который вы хотите быстро освободить (например, соединение с базой данных), и жизненно важный, когда есть неуправляемые ресурсы, которые вам нужно освободить. Типичная картина:

public void Dispose()
protected void Dispose(bool disposing)

Позволяет убедиться, что неуправляемые ресурсы высвобождаются либо методом Dispose, либо завершением объекта.

1 голос
/ 04 мая 2010

Вам не нужно освобождать память в управляемых объектах, таких как строки или массивы - это обрабатывается сборщиком мусора.

Вы должны очистить ресурсы операционной системы и некоторые неуправляемые объекты, когда вы закончите использовать их. Если вы открываете файл, вы всегда должны помнить о том, чтобы закрыть этот файл, когда вы закончили его использовать. Если вы откроете файл исключительно и забудете закрыть, при следующей попытке открыть этот файл он все равно может быть заблокирован. Если что-то реализует IDisposable, вы должны определенно подумать, нужно ли вам это правильно закрыть. В документации обычно указывается, что делает метод Dispose и когда его следует вызывать.

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

Также полезно знать о выражении using.

0 голосов
/ 04 мая 2010

Вам нужно только беспокоиться о драгоценных ресурсах. Большинство объектов, которые вы создаете во время программирования, не вписываются в эту категорию. Как вы говорите, сборщик мусора позаботится об этом.

Нужно помнить о том, что объекты, реализующие IDisposable, указывают на то, что принадлежащие ему ресурсы драгоценны и не должны ждать очистки потока финализатора. Единственный раз, когда вам понадобится реализовать IDisposable, это классы, которые владеют а) объектами, которые реализуют IDisposable (например, поток файлов), или б) неуправляемыми ресурсами.

0 голосов
/ 04 мая 2010

Сборщик мусора освобождает ПАМЯТЬ и очищает - посредством удаления - удаляет элементы, которые он удаляет. НО: ЭТО делает так, только когда у нее есть давление памяти.

Это серьезно идиотично для ресурсов, которые я могу явно опубликовать. Например, предполагается, что сохранение в файл: открыть файл, записать данные и - закрыть файл, чтобы пользователь мог скопировать его, если он этого хочет, БЕЗ ожидания, пока GC придет и освободит память для файлового объекта, что может не произойти в течение нескольких часов.

...