非托管资源和Dispose()

本文关键字:Dispose 资源 | 更新日期: 2023-09-27 18:14:19

我读了一些关于Dispose()方法的文章,发现非托管资源应该从Dispose()方法(或finalize()方法)中显式释放,文章说文件句柄和数据库连接对象是非托管资源的例子。有人能解释为什么这些是未管理的,如果在Dispose()中处理不当会发生什么吗?我不知道什么是文件句柄。它们存在于哪里?

非托管资源和Dispose()

在这种情况下,这样考虑可能是最简单的:

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

  • 唯一的其他资源是内存。如果它是由。net分配的,则会自动进行管理。(注意,有一些方法可以使用Windows API分配内存;

  • 是一个未管理的资源。

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

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

如果您不释放这些句柄,它们将在程序的持续时间内保持分配,但是所有具有非托管资源的。net类都提供Finalizer(见下文)以确保它们将在某个时刻正常释放

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

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

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

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

这是一种简化,但我希望它能帮助你理解它。

有关详细信息,请参阅有关处置模式的MSDN文章。

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

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