非托管资源和Dispose()
本文关键字:Dispose 资源 | 更新日期: 2023-09-27 18:14:19
我读了一些关于Dispose()
方法的文章,发现非托管资源应该从Dispose()
方法(或finalize()方法)中显式释放,文章说文件句柄和数据库连接对象是非托管资源的例子。有人能解释为什么这些是未管理的,如果在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堆对象,它可能拥有一些托管或非托管资源的组合,但如果它被放弃,其资源可能会被释放。