В чем разница между управляемыми и нативными ресурсами при утилизации? (.СЕТЬ) - PullRequest
25 голосов
/ 29 января 2009

Я читал статью MSDN о том, как реализовать IDisposable , и я не уверен в разнице между управляемыми и собственными ресурсами, процитированными в статье.

У меня есть класс, который должен располагать двумя своими полями при его удалении. Должен ли я относиться к ним как к управляемым (утилизировать только при утилизации = true) или к собственным ресурсам?

Ответы [ 3 ]

21 голосов
/ 21 апреля 2009

Чтобы добавить немного ответа Брайана и ваш комментарий / вопрос:

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

Чтобы помочь провести черту в песке, вот краткая (и, вероятно, пронизанная мелкими ошибками) версия того, как GC работает и очищает память:

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

Практически во всех случаях, работая с объектами .NET Framework, вы можете быть уверены, что объекты управляются (.NET предоставляет управляемые оболочки почти всех неуправляемых ресурсов для обеспечения их надлежащей очистки); другие сторонние компоненты, которые подключаются к Win32 API (или ваши компоненты, которые делают это), являются объектами, которые могут вызывать беспокойство.

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

Большинство «утечек памяти .NET» в действительности не являются утечками памяти. Обычно они происходят, когда вы думаете, вы удалили объект из использования, но на самом деле объект все еще имеет некоторую ссылку на приложение. Типичным примером является добавление обработчиков событий (obj.SomeEvent + = OnSomeEvent -or- AddHandler obj.SomeEvent, AddressOf OnSomeEvent), а не их удаление.

Эти «давние ссылки» технически не являются утечками памяти, поскольку ваше приложение все еще технически их использует; однако, если их достаточно, ваше приложение может испытать серьезное влияние на производительность и может показать признаки проблем с ресурсами (OutOfMemoryExceptions, невозможность получить дескрипторы окна и т. д.).

Я являюсь промежуточным разработчиком .NET и, к сожалению, знаю об этих проблемах из первых рук. Я рекомендую поиграть с ANTS Profiler, чтобы познакомиться с давними ссылками (есть бесплатная пробная версия) или если вы хотите получить немного больше подробных исследований, используя WinDbg и SOS.DLL, чтобы посмотреть на управляемую кучу. Если вы решите взглянуть на последнее, я рекомендую прочитать блог Тесс Феррандез; у нее много отличных уроков и советов по эффективному использованию Windbg

19 голосов
/ 29 января 2009

Управляемый ресурс - это другой управляемый тип, который реализует IDisposable. Вам нужно позвонить Dispose() на любой другой IDisposable тип, который вы используете. Собственные ресурсы - это что-то за пределами управляемого мира, например, собственные дескрипторы Windows и т. Д.


РЕДАКТИРОВАТЬ : ответ на вопрос в комментарии (слишком длинный для комментария)

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

1 голос
/ 21 апреля 2009

Коротким ответом будет то, что вы идете за спиной CLR (к ОС), которое можно получить, можно назвать « native ».

  • неуправляемое выделение памяти. Если вы «новый» кусок памяти в управляемом классе CantStayManaged, то CantStayManaged отвечает за освобождение этой памяти (ресурса).
  • относится к файлам, каналам, событиям, конструкциям синхронизации и т. Д. - в качестве правила большого пальца, если вы вызываете WinAPI для получения указателей / дескрипторов на ресурс, то это «собственные ресурсы»

Так что теперь у CantStayManaged есть 2 вещи, которые нужно очистить, прежде чем он предложит цену.

  1. Управляется: поля-члены и любые ресурсы, выделенные CLR. Обычно это приравнивается к вызову Dispose для ваших «одноразовых» объектов-членов.
  2. Неуправляемый: весь подлый материал низкого уровня, который мы тащим за его спиной.

Есть 2 способа очистки объекта.

  1. Dispose (true) case: вы явно вызвали Dispose для вашего типа. Хороший программист.
  2. Случай Dispose (false): вы забыли вызвать Dispose, и в этом случае финализатор должен включиться и все же обеспечить надлежащую очистку.

В обоих случаях неуправляемые ресурсы должны быть освобождены, иначе «LEAKS!», «CRASHES!» эт.все поверхности. Но вы должны пытаться очистить управляемые ресурсы только в первом случае Dispose (). В последнем случае / финализаторе - CLR, возможно, уже завершил работу и собрал некоторых ваших участников, поэтому вы не должны получать к ним доступ (CLR не гарантирует порядок, в котором завершается граф объектов). Следовательно, вы избегаете проблем путем защиты Ваша управляемая очистка с if (AmIBeingCalledFromDispose) проверкой охраны

НТН

...