非托管资源和Dispose()

时间:2013-05-20 09:59:10

标签: c# dispose unmanagedresources

我正在阅读一些关于Dispose()方法的文章,并发现应该从Dispose()方法(或finalize()方法)显式释放非托管资源,文章说文件句柄和数据库连接对象是示例非托管资源。任何人都可以解释为什么那些是不受管理的,如果在Dispose()中没有正确处理会发生什么?我不知道文件句柄是什么。它们存在于哪里?

2 个答案:

答案 0 :(得分:8)

在这种情况下,最简单的想法就是这样:

  • 非托管资源是通过进行Windows API调用而获得的任何资源,该API调用返回必须在某个时候释放的Windows Handle

  • 唯一的另一种资源是内存。如果它是由.Net分配的,则会自动管理。 (请注意,有一些方法可以使用Windows API分配内存;这可以算作非托管资源。)

例如,FileStream类调用Windows API来打开文件,FileStream在其中保留文件句柄。该文件句柄表示必须在某个时刻释放的非托管资源。

FileStream在幕后使用Windows API函数CreateFile()。它是从CreateFile返回的句柄,表示非托管资源。

如果你没有释放这些句柄,它们将在程序的持续时间内保持分配,但所有拥有非托管资源的.Net类都会提供Finalizer(见下文) )确保他们 通常会在某个时候被释放。

(但是如果您正在编写自己的文件处理类并忘记在任何地方释放文件句柄,则文件将保持打开状态,直到您的程序退出。)

通常,这些非托管资源将在两个位置释放:

  • Dispose()方法。这应该是您处置非托管资源的正常方式。

  • Finalizer。这是一种最后的手段。如果一个类有一个终结器,它将在垃圾收集器清理一个死对象时调用它。如果程序员忘记调用Dispose(),那么任何具有非托管资源的类都应该有一个终结器来清理。

这有点简化,但我希望能帮助你理解它。

有关详细信息,请参阅this MSDN article on the Dispose Pattern

答案 1 :(得分:2)

有些人认为非托管资源与Windows API调用或其他类似的东西有关,但这是一个实现细节。非托管资源的基本特征是它表示外部实体的状态的一个方面,该状态是为了拥有该资源的对象的利益而维护的,可能造成损害。如果所有对所有者的提及都被放弃,那么其他实体,以及外部实体将继续维持 - 无用 - 请注意,外部实体可以是任何地方,任何地方。 Windows API句柄代表了可能性的一小部分(获取句柄的对象要求Windows使系统的某些方面可供其独占使用,从而损害任何其他想要使用它们的代码)。外部实体完全可能在同一个程序集中(特别是如果资源是锁定或事件订阅),或者它可能在另一个大陆上(如果资源是远程计算机上的文件)。

对象通过通知代表它们的实体不再需要这样做来释放资源。托管资源是.NET堆对象,它可能拥有托管或非托管资源的某种组合,但如果资源被放弃,其资源可能会被释放。