代码之家  ›  专栏  ›  技术社区  ›  Nelson Rothermel

sqlconnection会被gc处理吗?

  •  10
  • Nelson Rothermel  · 技术社区  · 14 年前

    免责声明: 我知道 IDisposable 应在处理非托管资源时实现。其余的代码应该是确定性的 using (...) { } (相当于 try {} finally { Dispose(); } )确保尽快清理。此外,总承包商将 not call Dispose() ,因此建议的模式是重写 Finalize() 方法(在C中使用析构函数语法),然后调用 处置() . GC通常会 终结() (除非 GC.SuppressFinalize() 已被调用)。

    问题: 所以现在我把它弄走了,我有一个奇怪的场景,我做不到 using (SqlConnection...) { } 因为代码超出了我的控制。我通常可以做决定论的 处置() 但不能保证。我用反光镜拆卸 SqlConnection 并确保它使用dispose(),但除非我是盲人,否则没有终结器/析构函数( 终结() ~SqlConnection() )这是否意味着GC不会“清理”(发送回池)连接,在这种情况下我不能?我还没有找到任何确定的…

    1 回复  |  直到 14 年前
        1
  •  7
  •   Jon Hanna    14 年前

    好吧,它不会被处理,因为最终决定不是处理。

    决赛选手在 System.ComponentModel.Component 但它在 SQLConnection 的构造函数。这是一个好主意,如果你继承了一个决赛选手,你知道100%肯定你不会需要,但一个坏主意否则。在这种情况下,这是个好主意。

    不过,请记住 SqlConnection 是“真实”连接上的包装。实际上,它很可能是表示不同连接状态的变更对象集上的包装器。这是该机制的一部分,允许有效地汇集“真实”连接,就像每次调用 Open() 它从池中获取相关对象,并且每次调用 Close() (无论是直接,通过 Dispose() 或者离开 using )它会返回它。

    现在,请记住,只有直接保存非托管资源或其他不受GC关注的对象才需要最终确定。 连接对象 持有的对象可能(取决于 连接对象 )是一个拥有非托管资源的资源(或者实际上是更深层的类的嵌套)。因此没有必要 连接对象 最终确定。考虑三种可能的开放方式 连接对象 可以停止开放 连接对象 :

    1. 关闭() 被称为。这将立即返回到池的实际连接(如果没有池,则关闭池)。
    2. 处置() 被称为。这个电话 关闭() 同样的效果。
    3. 对象被垃圾收集。

    现在,在第三种情况下,对象持有对具有实际连接的对象的引用。它也是唯一这样做的对象。因此,该对象也将被垃圾收集。如果它有一个决赛选手(这很可能是这样的,尽管我不认为会有更多的聪明的把戏发生),那么决赛选手会把它放进决赛选手的队伍中,最终决赛。

    如果 连接对象 如果有决赛选手,唯一真正的效果是:

    1. 可能会出现错误代码(与最终代码中的最终成员打交道是很麻烦的,因为您不知道他们是否已经最终确定)。
    2. 减缓进程的潜力(真正的联系无论如何都会最终确定,充其量我们只是在放慢最终确定和GC的速度)。
    3. 无论如何,这里什么也不做(真正的联系将在没有任何帮助的情况下完成)。

    所以,让决赛选手 连接对象 是一场没有胜利的失败。而且,你真正的联系也应该最终敲定。

    这就是说,它离理想还有很远的距离 非常 可能泄漏连接。你能详细说明一下为什么不能打电话吗 关闭() 还是自己处理?管理连接的代码是否不能为您调用Close(对象应该结束其工作日) 在某处 ,应该关闭吗?

    你需要让它存活一段时间吗? IDataReader 或从 偶像崇拜者 是否允许完成?在这种情况下,你能用 CommandBehavior.CloseConnection 标记以便关闭(或处置)读卡器关闭连接?后一种情况是我能回忆起的唯一一种情况,即必须让连接离开未处理的范围。