Что такое неуправляемые ресурсы?


160

Я хочу знать о неуправляемых ресурсах. Кто-нибудь может дать мне основную идею?


Также смотрите эту страницу, которая дает фантастическое объяснение и образец для правильного использования IDisposable, и как принять во внимание неуправляемые ресурсы: stackoverflow.com/questions/538060/…
Кайл Баран

Ответы:


177

Под управляемыми ресурсами в основном подразумевается «управляемая память», которой управляет сборщик мусора. Если у вас больше нет ссылок на управляемый объект (который использует управляемую память), сборщик мусора (в конце концов) освободит эту память для вас.

Тогда неуправляемые ресурсы - это все, о чем сборщик мусора не знает. Например:

  • Открытые файлы
  • Открытые сетевые подключения
  • Неуправляемая память
  • В XNA: буферы вершин, индексные буферы, текстуры и т. Д.

Обычно вы хотите освободить эти неуправляемые ресурсы, прежде чем потеряете все ссылки, которые у вас есть на объект, управляющий ими. Вы делаете это, вызывая Disposeэтот объект или (в C #) используя usingоператор, который будет обрабатывать вызов Disposeдля вас.

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

Если вы реализуете класс самостоятельно, который обрабатывает неуправляемые ресурсы, вы должны правильно Disposeи Finalizeправильно его реализовать .


7
Подключение к открытой базе данных относится к какой категории? Управляемый / Неуправляемый?
Девипрасад Дас

8
+1 Другие ответы упускают важный момент, который вы вызываете Dispose для управляемого объекта, который внутренне обрабатывает освобождение неуправляемого ресурса, который он переносит (например, дескриптор файла, GDI + растровое изображение, ...), и что если вы обращаетесь к неуправляемым ресурсам напрямую ( PInvoke и т. Д.) Вы должны справиться с этим.
Ян Мерсер

2
@Dev: неуправляемый - поскольку GC не знает об этом (при условии, что вы не используете какую-то гипотетическую базу данных в управляемой памяти). Но объект соединения сам не может держать неуправляемый ресурс. Предположительно, соединение с базой данных использует открытый файл или подключение к сети где - то - но возможно , что другой объект (кроме объекта соединения) обрабатывает , что неуправляемый ресурс (возможно , библиотека базы данных кэшируют соединения). Проверьте документацию и посмотрите, где он просит вас позвонить Disposeили использовать using.
Эндрю Рассел

11
У меня есть базовый комментарий / вопрос по этому вопросу, могу ли я связать объект как управляемый / неуправляемый только по типу, например, строка является управляемой, DataSet неуправляемой (именно поэтому он имеет метод Dispose ()) , Соединения с базой данных являются неуправляемыми (потому что они располагают) и т. Д. Итак, есть ли предположение, если у него есть метод «Dispose ()», то он неуправляемый? В дополнение к этому, что бы объект XmlDocument был? Спасибо
Гандеры

15
@Ganders Это хорошее правило. Хотя помните, что все экземпляры класса C # являются управляемыми объектами. Если экземпляр класса может содержать неуправляемые ресурсы, то этот класс должен быть реализован IDisposable. Если класс делает реализации IDisposable, то вы должны избавиться от экземпляров этого класса с usingили , Dispose()когда вы сделали с ними. Исходя из этого, ваше обратное утверждение верно: если класс реализует IDisposable, то он, вероятно, содержит неуправляемые ресурсы внутри.
Эндрю Рассел

56

Некоторые пользователи ранжируют открытые файлы, соединения БД, выделенную память, битовые карты, файловые потоки и т. Д. Среди управляемых ресурсов, другие среди неуправляемых. Так они управляемые или неуправляемые?

Мое мнение таково, что ответ более сложный: когда вы открываете файл в .NET, вы, вероятно, используете какой-то встроенный класс .NET System.IO.File, FileStream или что-то еще. Поскольку это обычный класс .NET, им управляют. Но это обертка, которая внутри выполняет «грязную работу» (обменивается данными с операционной системой, используя библиотеки Win32, вызывая функции низкого уровня или даже инструкции ассемблера), которая действительно открывает файл. И это то, о чем .NET не знает, неуправляемый. Но вы, возможно, можете открыть файл самостоятельно, используя инструкции на ассемблере и обходя функции файла .NET. Тогда дескриптор и открытый файл являются неуправляемыми ресурсами.

То же самое с БД: если вы используете какую-то сборку БД, у вас есть классы, такие как DbConnection и т. Д., Они известны .NET и управляются. Но они оборачивают «грязную работу», которая неуправляема (выделять память на сервере, устанавливать с ней соединение, ...). Если вы не используете этот класс-обертку и самостоятельно открываете сетевой сокет и общаетесь со своей собственной странной базой данных, используя некоторые команды, это неуправляемо.

Этими классами-обертками (File, DbConnection и т. Д.) Управляют, но они внутри используют неуправляемые ресурсы так же, как вы, если вы не используете обертки и выполняете «грязную работу» самостоятельно. И поэтому эти обертки действительно реализуют шаблоны Dispose / Finalize. Они обязаны позволить программисту освобождать неуправляемые ресурсы, когда оболочка больше не нужна, и освобождать их, когда оболочка собирается мусором. Оболочка будет правильно собирать мусор сборщиком мусора, но неуправляемые ресурсы внутри будут собираться с использованием шаблона Dispose / Finalize.

Если вы не используете встроенные классы .NET или сторонние классы-обертки и открываете файлы с помощью некоторых инструкций ассемблера и т. Д. В вашем классе, эти открытые файлы неуправляемы, и вы ДОЛЖНЫ реализовать шаблон dispose / finalize. В противном случае произойдет утечка памяти, навсегда заблокированный ресурс и т. Д., Даже если вы больше не используете его (операция с файлом завершена) или даже после завершения работы приложения.

Но вы также несете ответственность за использование этих упаковщиков. Для тех, кто реализует dispose / finalize (вы узнаете их, что они реализуют IDisposable), внедрите также шаблон dispose / finalize и Dispose даже этих оболочек или дайте им сигнал освободить свои неуправляемые ресурсы. Если вы этого не сделаете, ресурсы будут освобождены через какое-то неопределенное время, но можно сразу же освободить их (немедленно закройте файл, не оставляя его открытым и заблокированным на случайные несколько минут / часов). Таким образом, в методе Dispose вашего класса вы вызываете методы Dispose всех используемых вами оболочек.


1
Хороший вопрос о дополнительной ясностиunmanaged vs managed resources
теперь тот, кого нельзя назвать.

спасибо за ваш ответ. На каких классах рекомендуется вызывать Dispose?
BKSpurgeon

2
Это просто В каждом классе, который вы используете, вы должны проверить, реализует ли он интерфейс IDisposable. Если да, то если вы используете такой класс в одном методе (например, открытие файла, сохранение текста, закрытие файла), вы можете использовать этот метод с помощью шаблона () {}, который автоматически вызывает Dispose для вас. Если вы используете такой класс в большем количестве методов (например, ваш класс содержит File, в конструкторе он открывает файл, затем несколько методов добавляют несколько журналов ...), то вы должны реализовать интерфейс IDisposable вашим классом, реализовать шаблон Dispose / Finalize и правильно распоряжаться объектом этого класса.
Martas

1
«... некоторый встроенный класс .NET System.IO.File, FileStream или что-то еще. Поскольку это нормальный класс .NET, им управляют». С уважением, это неправильно и вводит в заблуждение. Они не управляются . Если бы они были управляемыми, то вы могли бы выделить эти классы и ожидать, что сборщик мусора полностью обработает освобождение всех ресурсов детерминированным способом. Однако это приведет к тому, что дескрипторы файлов и неуправляемые ресурсы будут блокироваться и удерживаться гораздо дольше, чем необходимо, поскольку сборщик мусора не освободит класс и не завершит его потенциально в течение очень длительного времени.
AaronLS

1
@AaronLS в своем комментарии вы говорили о «FileStream», называя его неуправляемым, но это не так, хотя внутренне он использует неуправляемые ресурсы для своей работы. В управляемом мире Microsoft скрыла от вас множество неуправляемых вещей, внедрив распоряжаться рисунком. Управляемый код не означает, что он не использует неуправляемые ресурсы. Тем не менее, Microsoft проделала хорошую работу по внедрению IDisposable для этих типов объектов. Об этом свидетельствует тот факт, что он реализует IDisposable. В отношении этого доказательства мы должны считать его управляемым объектом.
Малик Халил

12

Неуправляемые ресурсы - это те, которые запускаются за пределами среды выполнения .NET (CLA) (иначе не код .NET). Например, вызов DLL в Win32 API или вызов DLL, написанный на C ++.


6

«Неуправляемый ресурс» - это не вещь, а ответственность. Если объект владеет неуправляемым ресурсом, это означает, что (1) некоторый объект за его пределами был обработан таким образом, что может вызвать проблемы, если он не очищен, и (2) объект обладает информацией, необходимой для выполнения такой очистки, и несет ответственность для этого.

Хотя многие типы неуправляемых ресурсов очень сильно связаны с объектами операционной системы различного типа (файлами, дескрипторами GDI, выделенными блоками памяти и т. Д.), Не существует единого типа объектов, который совместно используется всеми ними, кроме ответственности очистки. Как правило, если какой-либо объект несет ответственность за выполнение очистки, у него будет метод Dispose, который инструктирует ему выполнять всю очистку, за которую он отвечает.

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

Такие термины, как «управляемый ресурс» и «неуправляемый ресурс», к сожалению, используются разными людьми для обозначения разных вещей; Откровенно говоря, более полезно думать с точки зрения объектов как об отсутствии ответственности за очистку, об ответственности за очистку, о которой будет заботиться только при вызове Dispose, или об ответственности за очистку, о которой следует заботиться через Dispose, но которая может также позаботиться о Finalize.


5

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

Украденный отсюда , не стесняйтесь читать весь пост.


2

Любой ресурс, для которого выделена память в управляемой куче .NET, является управляемым ресурсом. CLR полностью осведомлена об этом виде памяти и сделает все, чтобы она не потеряла сознание. Все остальное неуправляемо. Например, взаимодействие с COM может создать объекты в области памяти процесса, но CLR об этом не позаботится. В этом случае управляемый объект, который выполняет вызовы через управляемую границу, должен нести ответственность за все, что находится за его пределами.


0

Давайте сначала разберемся, как выполнялись программы VB6 или C ++ (не Dotnet-приложения). Мы знаем, что компьютеры понимают только код машинного уровня. Код машинного уровня также называется собственным или двоичным кодом. Таким образом, когда мы выполняем программу на VB6 или C ++, соответствующий языковой компилятор компилирует исходный код соответствующего языка в собственный код, который затем может быть понят базовой операционной системой и оборудованием.

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

Давайте теперь разберемся, как работает программа .Net. Используя dotnet, мы можем создавать различные типы приложений. Некоторые из распространенных типов приложений .NET включают веб-приложения, приложения для Windows, консольные и мобильные приложения. Независимо от типа приложения, при запуске любого приложения .NET происходит следующее

  1. Приложение .NET компилируется в промежуточный язык (IL). IL также упоминается как общий промежуточный язык (CIL) и промежуточный язык Microsoft (MSIL). Приложения .NET и не .NET генерируют сборку. Сборки имеют расширение .DLL или .EXE. Например, если вы компилируете Windows или консольное приложение, вы получаете .EXE, тогда как, когда мы компилируем веб-проект или проект библиотеки классов, мы получаем .DLL. Разница между сборкой .NET и NON .NET заключается в том, что сборка DOTNET выполняется в формате промежуточного языка, а сборка NON DOTNET - в формате собственного кода.

  2. Приложения без DOTNET могут работать непосредственно поверх операционной системы, тогда как приложения DOTNET работают поверх виртуальной среды, называемой Common Language Runtime (CLR). CLR содержит компонент под названием Just In-Time Compiler (JIT), который преобразует промежуточный язык в нативный код, понятный базовой операционной системе.

Итак, в .NET выполнение приложения состоит из 2 шагов: 1. Компилятор языка, компилирует исходный код в промежуточный язык (IL) 2. Компилятор JIT в CLR преобразует IL в собственный код, который затем можно запустить в базовой операционной системе. ,

Поскольку сборка .NET имеет формат Intermedaite Language, а не собственный код, сборки .NET переносимы на любую платформу, если целевая платформа имеет Common Language Runtime (CLR). CLR целевой платформы преобразует язык Intermedaite в собственный код, понятный базовой операционной системе. Промежуточный язык также называется управляемым кодом. Это потому, что CLR управляет кодом, который выполняется внутри него. Например, в программе VB6 разработчик отвечает за освобождение памяти, используемой объектом. Если программист забывает освободить память, мы можем столкнуться с трудностями при обнаружении исключений из памяти. С другой стороны, программисту .NET не нужно беспокоиться о перераспределении памяти, используемой объектом. CLR обеспечивает автоматическое управление памятью, также известное как сбор мусора. Отдельно, от сборки мусора, есть несколько других преимуществ, предоставляемых CLR, которые мы обсудим на следующем занятии. Поскольку CLR управляет и исполняет промежуточный язык, он (IL) также называется управляемым кодом.

.NET поддерживает разные языки программирования, такие как C #, VB, J # и C ++. C #, VB и J # могут генерировать только управляемый код (IL), тогда как C ++ может генерировать как управляемый код (IL), так и неуправляемый код (собственный код).

Собственный код нигде не хранится постоянно, после того, как мы закрываем программу, нативный код выбрасывается. Когда мы снова запускаем программу, собственный код генерируется снова.

Программа .NET похожа на выполнение Java-программы. В Java у нас есть байт-коды и JVM (виртуальная машина Java), где, как и в .NET, у нас есть Intermediate Language и CLR (Common Language Runtime).

Это обеспечивается по этой ссылке - он отличный репетитор. http://csharp-video-tutorials.blogspot.in/2012/07/net-program-execution-part-1.html

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.