Managed и unmanaged resources в .NET
It specialist's tricks
# Managed и unmanaged resources в .NET
## Описание
Managed resources - ресурсы, которые автоматически очищаются, через Garbage collector.
Unmanaged resources - ресурсы, которые не очищаются с помощью Garbage collector и которые нужно явно очищать, после выполнения кода. Самые распространенные - это работа с файлами, соединение с БД, работа с областью памяти и т.д.
Для упрощения работы с Unmanaged resources, используется паттерн (интерфейс) IDisposable. В современных версиях .Net, этот интерфейс стал стандартом работы с неуправляемыми ресурсами, и оброс синтаксическим сахаром, например using, который позволяет, в пределах одного метода, ограничивать область существования такого ресурса, и вызывать метод Dispose(), в момент перехода исполнения кода, границы, выделенного под существование, участка.
## Нюансы
При работе с неуправляемым кодом, могут возникать утечки и проблемы параллельного и многопоточного доступа. Решаются они с помощью объектов CriticalFinalazerObject и SafeHandle.
CriticalFinalazerObject - объект, унаследовавшись от которого, объектам, работающим с внешними ресурсами, гарантируется вызов критичного финализатора, выполняющегося в CER контексте, охраняющего от асинхронных исключений, и ошибок параллельного доступа (всем нам известны эти случаи lock файлов, используемых сразу несколькими сервисами). Так же при завершении работы с этими объектами, CLR будет их уничтожать, при финализации других, использующих их, объектов. Прим.: используется редко.
SafeHandle - наследуется от CriticalFinalazerObject и реализует интерфейс IDIsposable, что позваляет работать с объектами, наследуемыми от него, работать с IntPtr, как с управляемыми ресурсами. Его можно использовать как и с директивой using, освобождая ресурсы в нужный момент, так и просто забывать про него, так как о нем позаботится Garbage collector, вызвав финализатор, в момент, когда исчезнет последняя ссылка на этот объект. Но последний подход - менее стабильный, так-как вызов Garbage collector может откладываться долго (по меркам процессора), поэтому для высокопроизводительных систем, всё-же, желательно использовать первый подход, или вызывать метод Close() или Dispose().
### Дополнительно
В C# 8, появился интерфейс IAsyncDisposable, который реализует то-же, что что и IDisposable, но так-же был добавлен метод DisposeAsync(), позволяющий не блокировать поток, при освобождении ресурсов, требующих длительного времени. Как пример, можно привести освобождение ресурса файла, расположенного на HDD носителе, загруженного до 100% различными W/R операциями, или соединение с БД, у которого ограниченно число одновременных запросов, с которой работает единовременно несколько сервисов. В таких случаях, нам не нужно блокировать целый поток, и занимать ресурсы процессора, и мы можем продолжать выполнение операций сравнения 0 и 1 на процессоре, дальше.
## Источники
https://learn.microsoft.com/en-us/dotnet/standard/managed-code
https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/
https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.safehandle?view=net-6.0
https://stackoverflow.com/questions/155780/safehandle-in-c-sharp