Подтвердить что ты не робот

Освободить ресурсы в .Net С#

Я новичок в С# и .NET, и читал об этом.

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

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

Спасибо.

4b9b3361

Ответ 1

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

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

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

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

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

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

Ответ 2

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

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

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

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

Ответ 3

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

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

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

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

Ответ 4

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

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

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

Также полезно знать о using.

Ответ 5

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

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

Ответ 6

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

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