2015-01-08 3 views
0

Я вижу много пример кода, который обертывает FileStream в блоке using или вызывает явно Dispose().Мне действительно нужно вызвать FileStream.Close/Dispose

Нужно ли мне это делать?

В моем (возможно упрощенном) понимании, C# представляет собой сборник данных, собранный с мусором, и когда объект выходит за пределы области видимости, он помечен для коллекции. Я предполагаю, что сборщик мусора достаточно умен, чтобы вызвать Dispose для меня на любом объекте, который IDisposable. Это правда?

Кроме того, я понимаю, что GC в C# не является детерминированным и не происходит непосредственно в ответ на объекты, выходящие из области видимости, по соображениям производительности. Итак, если я открываю миллион файлов в секунду, а не удаляя их, я могу создать много файлов. Это на самом деле проблема?

Я мог представить, что сборщик мусора на C# достаточно похож на GC в ответ на программу, которая поглощает системные ресурсы, такие как дескрипторы файлов. Даже если это не так, я могу представить, что открытые дескрипторы файлов в основном бесплатны в современной серверной ОС.

Значит, Dispose является педантичным?

+0

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

+0

Спасибо, Джон. Я указал на это, и это не мой вопрос. –

+2

Я видел, что приложение в производстве терпит неудачу, потому что оно не утилизировало экземпляры SmtpClient и исчерпало какой-то базовый ресурс, который он использует. Прошли месяцы, прежде чем условия были подходящими для этого. Если класс реализует IDisposable, его экземпляры должны быть явно удалены. – hatchet

ответ

4

Я считаю, что десятки или сотни существующих вопросов относительно IDisposable делают достойную работу по освещению этого вопроса. Тем не менее, обращаясь к вашим конкретным:

  1. «Я предполагаю, что сборщик мусора достаточно умен, чтобы вызвать Dispose для меня на любом объекте, который является IDisposable. Это правда?»

Да и нет. Объекты, которые реализуют IDisposable, обычно также реализуют финализатор. Это , что, который заставляет GC удалять объект перед сборкой.

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

  1. «Возможно, я создаю много файловых дескрипторов. Это на самом деле проблема?»

Да, это на самом деле проблема. В Windows теперь гораздо больше места для дескрипторов, чем раньше, но это все еще ограниченный ресурс.

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

  1. «Значит, это значит, что Dispose является педантичным?»

No. Вызов Dispose() на объекты (которые вы владеете, и не знаете, больше не нужно использовать) реализации IDisposable является важной частью любой правильной программы.

+0

Действительно приятное объяснение! Я думаю, что пункт 2 пропущен в большом количестве объяснений проблем с IDisposable! – mybirthname

+0

Просьба пояснить, что это не просто объекты, которые реализуют «IDisposable», это «объекты, которые вы создаете», которые реализуют IDisposable, или, точнее, «объекты, за которые вы несете ответственность». –

+0

@JohnSaunders: Я действительно не собирался перечислять здесь целую дискуссию «когда распоряжаться», и я думаю, что ответ будет без нее, но я добавил комментарий в любом случае. :) –

-3

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

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

+2

Неверное запоминание 'using'. 'using' сам по себе ничего не выделяет; это ярлык языка для записи блока 'try' /' finally' для обеспечения вызова метода 'Dispose()' объекта. –

Смежные вопросы