Удалите вопрос - PullRequest
       28

Удалите вопрос

10 голосов
/ 30 августа 2011

У меня есть несколько классов, которые имеют закрытые переменные-члены, которые реализуют IDisposable (таймеры, кисти и т. Д.).Нужно ли что-то делать, чтобы гарантировать, что эти переменные будут очищены .NET Framework должным образом?

Литература, с которой я столкнулся, ссылается на «управляемые ресурсы» против «неуправляемые ресурсы».Эти термины сбивают меня с толку, потому что вы можете иметь управляемый класс, который реализует функциональность, используя неуправляемые ресурсы.Это считается «неуправляемым ресурсом» или «управляемым ресурсом»?

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

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

Ответы [ 7 ]

9 голосов
/ 30 августа 2011

Да - если ваш класс "содержит" IDisposable, этот класс должен почти , безусловно, также реализует IDisposable.

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

Где это возможно, лучше , а не иметь такие члены класса в первую очередь - использовать их в качестве параметров метода локальных переменных и т. д., так что выможете использовать их, а затем закрыть их, не привязывая время жизни ресурса к времени жизни вашего объекта.Однако в некоторых случаях это не подходит - в этом случае вы должны реализовать IDisposable.

8 голосов
/ 30 августа 2011

Три простых правила.

Управляемый ресурс - это все, что реализует IDisposable. Неуправляемый ресурс - это что-то вроде HANDLE, которое вы получили через p / Invoke. Класс, подобный SafeHandle (или класс, производный от SafeHandle), владеет неуправляемым ресурсом, но считается самим управляемым ресурсом. Поэтому любой класс, которому принадлежит неуправляемый ресурс, сам по себе является управляемым ресурсом.

Поскольку у вас есть класс, владеющий управляемыми ресурсами, следуйте правилу 2: внедрите IDisposable (но не финализатор).

IDisposable допускает более раннюю очистку. Если вы не позвоните, ресурсы все равно будут очищены (они не будут зависать до завершения процесса); они просто будут очищены позже, и у вас нет выбора относительно , когда они будут очищены.

1 голос
/ 30 августа 2011

Очень подробные IDSposable рекомендации: здесь .

Транзитивно утилизируйте любые одноразовые поля, определенные в вашем типе от вашего метода утилизации.

Вы должны вызывать Dispose () для любых полей чей жизненный цикл контролирует ваш объект. Например, рассмотрим случай где ваш объект владеет частным полем TextReader. В вашем типе Dispose, вы должны вызвать Dispose объекта TextReader, который будет в свою очередь распоряжаться своими одноразовыми полями (Stream и Encoding, для пример) и тд. Если реализовано внутри Dispose (удаление bool) метод, это должно происходить, только если параметр размещения true - касание других управляемых объектов не допускается во время финализации. Кроме того, если ваш объект не владеет данным одноразовый предмет, он не должен пытаться утилизировать его, как другие код все еще может полагаться на его активность. Оба из них могут привести к обнаруживаемые ошибки.

Реализуйте шаблон утилизации, когда ваш тип распечатан и содержит ресурсы, которые явно должны быть или могут быть освобождены, для пример необработанных дескрипторов или других неуправляемых ресурсов.

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

«Неуправляемый ресурс» обычно относится к случаям, когда ваш код ссылается на собственные дескрипторы напрямую (файловые дескрипторы, соединения, сокеты и т. Д.). В этом случае вам также потребуется реализовать финализатор или использовать SafeHandle . Большую часть времени вы ссылаетесь на собственные дескрипторы косвенно через классы .NET, такие как TextReader. В этом случае вы можете просто использовать 'using' или, если вы пишете библиотеку, реализовать IDisposable транзитивно.

1 голос
/ 30 августа 2011

У вас есть хорошая информация и некоторая дезинформация в вашем понимании.

Короче говоря, вам нужно Dispose() все, что реализует IDisposable.

Быть какэто частные переменные-члены вашего класса, и , если они должны быть доступны в течение времени существования экземпляров этого класса, ваш класс должен также реализовать IDisposable и Dispose() этих типов в своем собственномDispose() method.

Если эти закрытые переменные-члены имеют ограниченное время жизни (т.е. только в одном методе), просто оберните их в блок using.

1 голос
/ 30 августа 2011

Если в вашем классе есть переменные-члены, которые реализуют IDisposable, то ваш класс должен также реализовать его. Вы убираете то, что у вас есть.

0 голосов
/ 31 августа 2011

Я думаю, что наиболее полезно описать управляемый ресурс - это объект типа класса, который реализует IDisposable и требует очистки, но может выполнить такую ​​очистку (обычно с использованием Finalize), если он был оставлен без надлежащего удаления. Неуправляемый ресурс, как правило, относится к объекту, который требует очистки, которая просто не произойдет, если он будет оставлен без предварительного удаления. Важно отметить, что хотя термин «управляемый ресурс» относится по существу исключительно к объектам типа класса (которые обычно переопределяют Finalize, но которые в некоторых случаях могут быть целью объектов WeakReference), неуправляемые ресурсы могут быть не только равными * 1001. * что-нибудь , они также могут быть где-нибудь , в том числе на другом компьютере.

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

Простая категоризация вещей как «управляемых ресурсов» или «неуправляемых ресурсов» не совсем достаточна для принятия решения о том, как их следует очищать. Некоторые неуправляемые обязанности могут быть удобно обработаны оберткой типа класса, которая может выполнить любую необходимую очистку в случае ненадлежащего отказа. Такие обертки, как правило, должны содержать минимальное количество информации, необходимой для выполнения очистки. Другие обязанности не могут быть выполнены автоматически. Часто лучше обеспечить вызов Dispose, чем пытаться обрабатывать все, что может произойти, если это не так.

0 голосов
/ 30 августа 2011

1) Вы можете использовать инструмент Memory Profiler Tool, в Интернете их много, лучше всего я знаю, что это ANTS Profiler от Reg Gate.

2) Мое эмпирическое правило заключается в том, что события всегда должны быть отписаны, и одноразовые объекты (потоки и т. Д.) Будут автоматически удаляться, если они являются переменными-членами и объект, содержащий их, уничтожается. Если вы, например, создаете локальный одноразовый объект в методе, вы должны удалить его или просто поместить в оператор using и забыть об этом;)

...