检测是否调用了垃圾收集器(.Net)

检测是否调用了垃圾收集器(.Net),.net,garbage-collection,timer,sqlconnection,.net,Garbage Collection,Timer,Sqlconnection,使用SqlConnection时,务必在使用时将其关闭-通过.close()或将SqlConnection置于“使用”位置。令人惊讶的是,人们,包括我自己,往往忘记了这一点,这就是垃圾收集器救了我一段时间,直到我忘记关闭连接太多次,或者使用该应用程序的人数增加 我想知道,如果可能的话,如何检测垃圾收集器是否处理了SqlConnection,因为它认为它已不再使用,或者SqlConnection是否以正确的方式关闭 另一种方法是继承SqlConnection并在其初始值设定项上放置计时器,然后检查

使用SqlConnection时,务必在使用时将其关闭-通过.close()或将SqlConnection置于“使用”位置。令人惊讶的是,人们,包括我自己,往往忘记了这一点,这就是垃圾收集器救了我一段时间,直到我忘记关闭连接太多次,或者使用该应用程序的人数增加

我想知道,如果可能的话,如何检测垃圾收集器是否处理了SqlConnection,因为它认为它已不再使用,或者SqlConnection是否以正确的方式关闭

另一种方法是继承SqlConnection并在其初始值设定项上放置计时器,然后检查在处理类时关闭连接所用的时间。我真的不喜欢计时器,但这个想法是在写这篇文章时产生的

也许还有第三种更聪明的方法。。。你推荐什么

一条经验法则是,“如果你不得不考虑垃圾收集器,你可能做错了什么。”(当然,还有其他的拇指…)

在我看来,确保连接被明确关闭或通过
使用
最后
块关闭是最好的途径


显然,您已经了解了这些技术。。。因此,您可能只需要一次完整的代码和一次可能的重构。

如果忘记处理,对象将最终确定。无法控制发生这种情况的时间,也无法知道对象是否已完成。为了最终确定对象,必须创建一个单独的线程,这样会减慢应用程序的速度。这就是为什么你要处理。在框架中实现IDisposable的所有类中,都会调用GC.SuppressFinalize,因此对象不会最终确定

你无法控制这种行为。如果您的对象不再使用,它将自动收集。你所能做的就是打电话给GC.SuppressFinalize,但我不建议你这么做,因为如果你忘记了,你会一辈子倒霉的


您可以创建一个包装类(而不是子类),您可以在代码中使用它来提供一些始终调用Dispose的简单方法。否则,请仔细检查。

因为SqlConnection是密封的,所以您将无法从中继承。(我认为这样做不是一个好主意——如果可能的话,您可能应该在Dispose(false)中添加代码,因为终结器就是这样调用的)

最好使用静态代码分析工具来检测此类问题,该工具可以检测代码中忘记处理连接的所有位置。有一个内置的,或者你可以使用

为了帮助您不要忘记处理连接,最好:

  • 将所有DB连接代码保存在一个层/程序集/模块中,这样它就不会分散在项目中
  • 具有执行SQL命令和返回结果的实用方法;因此,创建SQLConnection的位置不会超过需要的数量
  • 记住要利用这个工具

如果您的应用程序使用SQL连接池(默认设置),这将无关紧要,因为连接会被重复使用,并且在调用.Close()或留下using(){}块时不会关闭

为了回答您的问题,我不相信GC收集有事件,但是如果有,这并不重要,因为您永远不会知道GC是否选择在该收集过程中回收您的对象(并非所有对象都会因为分代算法而被清理)


我也会避免使用计时器和“检查”的尝试,因为您可能会持有对对象的引用,并阻止它被处理。

首先,如果您甚至考虑使用GC,您可能会遇到严重的问题。我建议确保代码调用接近的最好方法是使用以下技术对代码进行单元测试:。如果单元测试表明调用了Close,那么代码是正确的,您不必做任何不必要的危险事情,比如乱动垃圾收集器


第二,如果你仍然坚持运行时检查路线,你应该考虑的唯一事情就是钩住<代码> SqLink连接< /代码>的事件。例如,如果连接状态从打开变为关闭,则会触发此操作。

我对垃圾回收器不太熟悉,也不知道是否有直接的方法获取信息,但我的第一个想法是以下方法

只需创建一个虚拟对象。如果稍后查看弱引用,并且对象不再是弱引用,则可能会假定发生了垃圾收集


(这个答案只适用于检测垃圾收集器运行。我完全忽略了这样做的原因——有更好的策略来处理资源泄漏。)

+1解决此问题的最佳方法是找出根本原因并处理连接。但这很重要,因为如果连接未关闭,则不会返回到池中,因此不会立即重新使用。这可能会耗尽您的连接池或消耗有价值的资源,从而导致问题。同意,但问题是OP想知道垃圾回收何时发生。我的观点是,sql连接的收集不会发生在池中。唯一的解决方案是实际修复并确保调用.Close(),而不是依赖于GC collect事件或计时器检查。
by.Close()或将SqlConnection置于“using”
NO。Close()本身不够好。这就是使用构造的
的全部要点:太多人也忘记了.Close()必须在finally块中。这就是全部要点,您需要进行处置以防止终结。如果你只是保持一个弱的裁判,并检查它是否发生了,你已经太晚了。