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

Определение управляемых и неуправляемых ресурсов

Есть много вопросов об управляемых vs неуправляемых ресурсах. Я понимаю основное определение этих двух. Тем не менее, мне сложно знать, когда ресурс или объект управляются или неуправляемы.

Когда я думаю о неуправляемых ресурсах, я склонен думать о собственном коде, который не является непосредственно частью .NET, например, pinvoke или marshaling resources. Обычно я думаю о ресурсах, предназначенных для взаимодействия с тем, что будет использовать HW, такие как дескриптор файла или сетевое соединение, также неуправляемые.

Что относительно объектов .NET, которые обертывают собственные неуправляемые ресурсы, такие как FileStream.

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

До сих пор я предполагал, что если объект реализует IDisposable, тогда он управляется. Как я узнаю, что IntPtr следует обрабатывать как неуправляемый resoruce?

4b9b3361

Ответ 1

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

FileStream - это управляемый ресурс.

Управляемые ресурсы - это классы, которые содержат (и должны управлять) неуправляемыми ресурсами. Обычно фактический ресурс имеет несколько уровней.

До сих пор я предполагал, что если объект реализует IDisposable, тогда он управляется.

Правильно.

Как я узнаю, что IntPtr следует обрабатывать как неуправляемый resoruce?

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

Ответ 2

Это довольно прямолинейно, вы никогда не можете случайно выделить неуправляемый ресурс. Для его выделения требуется вызов pinvoke, вы об этом знаете. Термин "объект" перегружен, но нет такой вещи, как неуправляемый объект, все объекты в программе .NET управляются. Вы можете взаимодействовать с кодом, написанным на другом языке, который поддерживает создание объектов, таких как С++. Но вы не можете напрямую использовать такой объект, требуется оболочка С++/CLI. Это делает его управляемым классом, который реализует IDisposable.

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

Задача Microsoft заключалась в предоставлении управляемых оболочечных классов по всем общим ресурсам операционной системы. Подобно FileStream, Socket и т.д. Эти классы почти всегда реализуют IDisposable. Единственное, что вам нужно сделать в вашем коде при хранении такого объекта класса в своем собственном классе, - это реализовать IDisposable самостоятельно, просто вы вызываете метод Dispose() для этого объекта. Или используйте оператор using, если вы используете их как локальную переменную в методе.

Ответ 3

В этом контексте наиболее полезно подумать о "ресурсе", означающем "то, что объект попросил что-то еще сделать от его имени, до дальнейшего уведомления, в ущерб всем остальным". Объект представляет собой "управляемый ресурс", если отказ от него приведет к тому, что сборщик мусора, уведомляющий объект отказа, и объект, в свою очередь, инструктирует все, что действует от его имени, чтобы прекратить это делать. "Неуправляемый ресурс" - это ресурс, который не инкапсулирован в управляемый ресурс.

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

Хотя API-интерфейсы являются наиболее распространенным видом неуправляемого ресурса, существует множество других видов. Такие вещи, как блокировки и события монитора, полностью существуют в мире управляемых кодов .net, но тем не менее могут представлять собой неуправляемые ресурсы, так как получение блокировки и отказ от ожидающего ожидания кода могут привести к тому, что этот код будет ждать навсегда, а так как недолговечный объект, который подписывается на событие от долгоживущего объекта и не может отказаться от подписки до его отказа, может привести к тому, что долгоживущий объект будет продолжать бесконечно переносить ссылку на событие (небольшая нагрузка, если только один абонент будет оставлен, но неограниченное бремя если неограниченное количество подписчиков создано и покинуто).

Добавление Основополагающим предположением сборщика мусора является то, что, когда объект X содержит ссылку на объект Y, это потому, что X "заинтересован" в Y. Однако в некоторых ситуациях ссылка может быть проведена, потому что X хочет, чтобы Y держала ссылку на это даже несмотря на то, что Y не "заботится" так или иначе. Такие ситуации часто возникают с обработчиками событий уведомлений. Объект Y может быть уведомлен каждый раз, когда что-то происходит с объектом X. Хотя X должен хранить ссылку на Y, чтобы он мог выполнять такие уведомления, сам X не заботится об уведомлениях. Он выполняет их только из-за предположения, что какой-то внедренный объект может заботиться о том, чтобы Y получал их.

В некоторых случаях можно использовать то, что называется "шаблон слабых событий". К сожалению, хотя в .net существует множество слабых шаблонов событий, все они имеют причуды и ограничения из-за отсутствия надлежащего типа WeakDelegate. Кроме того, хотя слабые события полезны, они не являются панацеей. Предположим, например, что Y попросил долгоживущий объект X уведомить его, когда что-то случится, единственная существующая ссылка на Y - это один X, используемый для такого уведомления, единственное, что Y делает с таким уведомлением, чтобы увеличить свойство в каком-то объекте Z, и что установка этого свойства ничего не изменяет вне Z. В этом сценарии, хотя объект Z будет единственной вещью во Вселенной, которая "заботится" об объекте Y, Z не будет содержать никакой ссылки на Y, и, следовательно, сборщик мусора не сможет привязать время жизни Y к Z. Если a X содержит сильную ссылку на Y, последний будет сохранен даже после того, как никто не заинтересован в нем. Если X содержит только слабую ссылку, то Y может быть собрано в мусор, даже если Z заинтересован в нем. Нет механизма, с помощью которого сборщик мусора может автоматически заключить, что Z интересует Y.