【问题标题】:Unmanaged resources and Dispose()非托管资源和 Dispose()
【发布时间】:2013-05-20 09:59:10
【问题描述】:

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

【问题讨论】:

    标签: c# dispose unmanagedresources


    【解决方案1】:

    在这种情况下,可能最容易这样想:

    • 非托管资源是通过 Windows 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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-02-02
        • 2013-05-12
        • 2023-03-26
        • 2019-08-02
        • 1970-01-01
        • 2015-05-27
        • 2012-05-06
        • 1970-01-01
        相关资源
        最近更新 更多