我正在阅读一些关于Dispose()
方法的文章,发现非托管资源应该从Dispose()
方法(或 finalize() 方法)中显式释放,并且文章说文件句柄和数据库连接对象是非托管资源的示例。谁能解释为什么这些是不受管理的以及如果在 Dispose() 中处理不当会发生什么?我不知道文件句柄是什么。它们存在于哪里?
2 回答
在这种情况下,可能最容易这样想:
非托管资源是通过 Windows API 调用获得的任何资源,该调用返回
Windows Handle
必须在某个时候释放的 a。唯一的另一种资源是内存。如果它是由 .Net 分配的,则会自动管理它。(请注意,有一些方法可以使用 Windows API 分配内存;这算作非托管资源。)
例如,FileStream
该类调用 Windows API 来打开一个文件,该文件在FileStream
内部保留一个文件句柄。该文件句柄表示必须在某个时候释放的非托管资源。
FileStream
CreateFile()
在幕后使用 Windows API 函数。它是CreateFile
代表非托管资源的返回句柄。
如果您不释放这些句柄,它们将在程序运行期间保持分配状态,但所有具有非托管资源的 .Net 类都提供Finalizer
(见下文)以确保它们通常会在某个时候被释放。
(但是,如果您正在编写自己的文件处理类并且根本忘记在任何地方释放文件句柄,那么文件将保持打开状态,直到您的程序退出。)
通常,此类非托管资源将在两个地方释放:
Dispose() 方法。这应该是您处置非托管资源的正常方式。
Finalizer
。_ 这是最后的机制。如果一个类有一个终结器,垃圾收集器在清理死对象时会调用它。如果程序员忘记调用 Dispose(),任何具有非托管资源的类都应该有一个终结器来清理。
这有点简化,但我希望它会帮助你理解它。
有关详细信息,请参阅有关 Dispose Pattern 的这篇 MSDN 文章。
有些人认为非托管资源与 Windows API 调用或其他类似的东西有关,但这是一个实现细节。非托管资源的基本特征是它代表外部实体的一个方面为拥有资源的对象的利益而维护的状态,可能损害其他实体,并且如果放弃对所有者的所有引用,外部实体将继续维护(无用)。请注意,外部实体可以是任何地方的任何东西。Windows API 句柄代表了可能性的一小部分(获取句柄的对象要求 Windows 使系统的某些方面可供其独占使用,从而损害任何其他想要使用它们的代码)。外部实体完全有可能在同一个程序集中(特别是如果资源是锁或事件订阅),或者它可能在另一个大陆(如果资源是远程机器上的文件)。
一个对象通过通知代表它的实体他们不再需要这样做来释放资源。托管资源是一个 .NET 堆对象,它可能拥有托管或非托管资源的某种组合,但如果被放弃,其资源可能会被释放。