我正在阅读关于“内存管理和指针”的Wrox's Professional C# 4 and .NET 4章节,特别是关于垃圾收集在.NET中如何工作的内容。它说“垃圾收集器不知道如何释放非托管资源(例如文件句柄,网络连接和数据库连接)”的原因,这就是为什么这些类应该声明析构函数(又名“终结者”)或实施IDisposable
。
似乎所有这些“非托管资源”的示例都与从应用程序外部并独立于.NET Framework的系统交互相关。但是,我不确定这是否是正在进行的完全区分,所以,
答案 0 :(得分:3)
你做得对:
托管资源由CLR管理,非托管资源不管理。换句话说:托管资源仅存在于.NET世界中,而非托管资源来自正常的Win32世界。
答案 1 :(得分:2)
使用托管资源(即内存),您不必担心使用它们后会发生什么; CLR负责这一点。
非托管资源(有几种类型:Windows内核对象,GDI对象,USER对象)必须在完成使用后释放回系统。当您的进程终止时会自动发生这种情况,但如果它在此期间泄漏它们,则会出现一个大问题,因为您正在泄漏系统中所有进程之间共享的资源。
当然,.NET中有几个类包装这些非托管资源(使用dispose/finalize pattern)并为您完成艰苦的工作。如果可以,请使用它们。
答案 2 :(得分:0)
我想说通常使用.Net框架创建的任何东西都是托管资源。在内部,他们可能会使用非托管资源,但从您的角度来看,他们是受管理的。其中一个例外是你P / Invoke。虽然您创建了一个与.Net一起使用的函数,但是调用会在.Net“沙箱”之外传递,因此被认为是不受管理的。
对@supercat的响应
来自长期存在的对象的事件可能完全在.net框架内处理,但它们肯定需要被视为非托管资源以防止内存泄漏
我认为这里有两个不同的东西。有关托管与非托管的讨论,并讨论了应用程序的内存管理。您可能应该将某些对象视为不受管理,但这并不意味着它们不受管理。例如,我会考虑管理Brush
类,但您应该通过调用Dispose()
将其视为非托管类。在类中隐藏/抽象是您希望Dispose()
负责的非托管对象。但是Dispose()
实际上并没有释放任何资源,它只是一种你希望开发人员正确实现的模式。
为了更进一步,我想说大多数非托管对象是通过调用CreateXYZ()
Win32方法创建的,该方法返回一个指针,但是需要使用`DestroyXYZ()/ DeleteXYZ()'方法来释放它。指针。另一方面,托管对象实现Dispose / Finalize为您执行此操作。再一次,您希望托管资源的编写者已经做到了这一点,但不能保证。
答案 3 :(得分:0)
“非托管资源”一词令人困惑。一个更有用的概念是“清理责任”。如果一个对象拥有非托管资源,那意味着三件事:
通常,术语“托管资源”用于表示保存非托管资源的对象,但如果发现它们被放弃,它们将从垃圾收集器(通过Finalize例程)接收通知,并且将使用此类通知提供清理(如果他们在调用正常的清理方法之前被放弃)。有些人使用术语“托管资源”来指代不需要任何清理的东西,但我不喜欢这样的用法,因为没有任何其他好的术语来指代应该手动清理的东西但是如果没有发生正常清理,将使用finalization作为后备。
请注意,虽然非托管资源通常是文件的OS句柄,GDI实体等,但用这样的术语来思考它们是错误的。可能有非托管资源不能访问.Net框架之外的任何内容;事件处理程序就是一个常见的例子。非托管资源的关键方面是它们需要清理,未能执行此类清理会产生一些不良后果。