在.NET中,“managed”和“unmanaged”资源是什么意思?

149

在 .NET 中,什么是托管资源和非托管资源?它们是如何出现的?


可能是什么是C#中的托管/非托管代码?的重复问题。 - T.Todua
5个回答

110
术语“未托管资源”通常用于描述某些东西,即“不直接受垃圾回收器控制”。例如,如果您打开与数据库服务器的连接,则会在服务器上使用资源(以维护连接),并且如果提供程序不完全以托管代码编写,则可能在客户端机器上使用其他非 .net 资源。
这就是为什么建议您编写此类内容时应采用如下方式:
using (var connection = new SqlConnection("connection_string_here"))
{
    // Code to use connection here
}

这样可以确保在连接对象上调用.Dispose(),从而确保清理所有未管理的资源。


27
我稍微澄清一下:未受管理的资源是指如果该资源被遗弃,垃圾回收器不知道如何清理它。例如,短暂存在的对象订阅了长期存在对象的事件,即使两个对象都在垃圾回收器的控制之下,该订阅仍然是未受管理的资源,因为垃圾回收器无法知道如果订阅者被遗弃但发布者没有被遗弃,订阅应该被废弃。如果在发布者的生命周期内可以创建和遗弃无限数量的订阅者,那将导致内存泄漏。 - supercat
14
添加一些澄清:SqlConnection(或FileStream等)是托管资源,其内部使用GC不知道的非托管资源。 - jimvfr
3
Jimvfr是正确的,SqlConnection是托管资源的一个例子。非托管资源的一个例子是当我们需要使用方法Marshal.AllocHGlobal()从非托管内存中分配内存时,它是一个非托管资源。在这种情况下,最佳实践是使用析构函数(~ ctor)并调用Marshal.FreeHGlobal()释放此内存。 - Ygor Thomaz
请问您能否举出托管和非托管资源的例子? - Radha Manohar

45

托管资源是指纯.NET代码,由运行时管理并受其直接控制的资源。

非托管资源是指不是由运行时管理的资源,例如文件句柄、固定内存、COM对象、数据库连接等。


25
在Q&A 什么是非托管资源?1中,Bruce Wood发表了以下观点:

我这样理解"托管"和"非托管"这两个词:

"托管"指的是.NET沙箱内的任何内容。这包括所有.NET Framework类。

"非托管"指的是.NET沙箱之外的荒野。这包括通过调用Win32 API函数返回给您的任何内容。

如果您从未调用过Win32 API函数,也没有获得任何Win32“句柄”对象,则不持有任何非托管资源。通过.NET Framework类方法打开的文件和流都是托管封装器。

评论:您可能没有直接持有非托管资源。但是,您可能通过托管的“包装类”(例如System.IO.FileStream)间接持有非托管资源。这样的包装类通常直接或通过继承实现IDisposable
许多托管(.NET Framework)对象内部都持有非托管资源,您可能希望尽快Dispose()它们,或者至少给调用者提供这样的机会。这就是编写自己的Dispose()方法的作用。实现IDisposable()基本上为您执行两件事情: 1. 允许您摆脱从.NET背后直接获取的任何资源(非托管资源)。 2. 允许您和您的调用者释放笨重的.NET对象/持有宝贵资源的.NET对象,这些对象正紧握在您/您的调用者的手中,您/您的调用者现在想要释放它们。
评论:通过实现IDisposable并提供Dispose()方法,您使得使用您的类的用户能够以确定性方式释放由类实例持有的任何非托管资源。

1 链接最初由 Sachin Shanbhag's answer 分享。引用材料日期为2005年11月17日。请注意,我已经轻微地编辑了引用的内容。


9
一个托管资源和非托管资源之间的基本区别是垃圾回收器知道所有托管资源,垃圾回收器会在某个时间点清理与托管对象相关的所有内存和资源。垃圾回收器不知道非托管资源,例如文件、流和句柄,如果您没有在代码中显式清理它们,那么您将最终面临内存泄漏和锁定资源的问题。
更多详情请参见- http://bytes.com/topic/c-sharp/answers/276059-what-unmanaged-resources

2
IDisposable 接口背后的想法是让您以确定性方式清理资源并清理非托管资源。太棒了! - zionpi

2

托管资源是可以被垃圾回收器释放的资源,而非托管资源则不能被垃圾回收器释放。因此需要使用析构函数来释放非托管资源。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接