繁体   English   中英

.NET中的托管与非托管资源。有什么不同?

[英]Managed vs Unmanaged Resources in .NET. What's the difference?

我正在阅读Wrox的专业C#4和.NET 4章节“内存管理和指针”,特别是关于Garbage Collection如何在.NET中运行。 它说“垃圾收集器不知道如何释放非托管资源(例如文件句柄,网络连接和数据库连接)”的原因,这就是为什么这些类应该声明析构函数 (也称为“终结器”)或实现IDisposable

似乎所有这些“非托管资源”的示例都与从应用程序外部并独立于.NET Framework的系统交互相关。 但是,我不确定这是否是正在进行的完全区分,因此,

非托管资源和托管资源没有的独特特征究竟是什么?

你做对了:
托管资源由CLR管理,非托管资源不管理。 换句话说:托管资源仅存在于.NET世界中,而非托管资源来自正常的Win32世界。

使用托管资源(即内存),您不必担心使用它们后会发生什么; CLR负责这一点。

非使用资源(有几种类型:Windows内核对象,GDI对象,USER对象) 必须在使用完后释放回系统 当您的进程终止时会自动发生这种情况,但如果它在此期间泄漏,则会出现一个大问题,因为您正在泄漏系统中所有进程之间共享的资源。

当然,.NET中有几个类包装这些非托管资源(使用dispose / finalize模式 )并为您完成艰苦的工作。 如果可以,请使用它们。

我会说,通常使用.Net框架创建的任何东西都是托管资源。 在内部,他们可能会使用非托管资源,但从您的角度来看,他们是受管理的。 其中一个例外是你P / Invoke。 虽然您创建了一个与.Net一起使用的函数,但是调用会在.Net“沙箱”之外传递,因此被认为是不受管理的。

对@supercat的回应

来自长期存在的对象的事件可能完全在.net框架内处理,但它们肯定需要被视为非托管资源以防止内存泄漏

我认为这里有两个不同的东西。 有关托管与非托管的讨论,并讨论了应用程序的内存管理。 您可能应该将某些对象视为不受管理,但这并不意味着它们不受管理。 例如,我会考虑使用Brush类进行托管,但是你应该通过调用Dispose()将其视为非托管类。 在类中隐藏/抽象是您希望Dispose()负责的非托管对象。 Dispose()实际上并没有释放任何资源,它只是一个你希望开发人员正确实现的模式。

为了更进一步,我想说大多数非托管对象是通过调用CreateXYZ() Win32方法创建的,该方法返回一个指针但需要使用带有相同指针的`DestroyXYZ()/ DeleteXYZ()'方法释放。 另一方面,托管对象实现Dispose / Finalize为您执行此操作。 再一次,您希望托管资源的编写者已经做到了这一点,但并不能保证。

“非托管资源”一词令人困惑。 一个更有用的概念是“清理责任”。 如果一个对象拥有非托管资源,那意味着三件事:

  1. 它操纵一些外部长寿的实体,
  2. 该实体可能处于需要清理的状态,并且
  3. 该对象负责提供所需的清理

通常,术语“受管资源”用于表示保存非托管资源的对象,但如果发现它们被放弃,它将从垃圾收集器接收通知(通过Finalize例程),并且将使用此类通知提供清理(​​如果在调用正常的清理方法之前它们被放弃了)。 有些人使用术语“托管资源”来指代不需要任何清理的东西,但我不喜欢这样的用法,因为没有任何其他好的术语来指代应该手动清理的东西但是将使用finalization作为后备,以防正常清理不发生。

请注意,虽然非托管资源通常是文件的OS句柄,GDI实体等,但用这样的术语来思考它们是错误的。 可能有非托管资源不能访问.Net框架之外的任何内容; 事件处理程序就是一个常见的例子。 非托管资源的关键方面是它们需要清理,而未能执行此类清理会产生一些不良后果。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM