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

发布于 2024-09-07 04:00:05 字数 377 浏览 2 评论 0原文

使用 SqlConnection 时,重要的是在使用时始终关闭它 - 通过 .Close() 或将 SqlConnection 放在“using”中。不幸的是,人们,包括我自己,往往会忘记这一点,这就是垃圾收集器暂时拯救我的地方,直到我忘记关闭连接太多次或者使用该应用程序的人数增加。

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

另一种方法可以是继承 SqlConnection 并在其初始化程序上放置一个计时器,并在处置该类时检查连接关闭所需的时间。我不太喜欢计时器,但这个想法是在写这篇文章时出现的。

也许还有第三种甚至更聪明的方法来解决这一切......您会推荐什么?

When using SqlConnection, it's important to always close it when used - either by .Close() or placing the SqlConnection in a "using". Unfurtunately, people, including myself, tend to forgot that and this is where the garbage collectors rescues me for a while until i've forgot to close my connections too many times or the number of people using the application grows.

I'd like to know, if even possible, how to detect if the garbage collector disposed the SqlConnection because it figured that it wasn't in use anymore or if the SqlConnection was closed the correct way.

Another way could be inheriting SqlConnection and putting a timer on it's initializer and check how long it took for the connection to be closed when disposing the class. I don't really like timers but the idea just came up while writing this.

Maybe there's a third and even smarter way to all this... What would you recommend?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

绻影浮沉 2024-09-14 04:00:05

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

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

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

  • 将所有数据库连接代码保留在一层/程序集/模块中,这样它就不会分散在项目中。
  • 具有执行SQL命令并返回结果的实用方法;因此,您创建 SQLConnection 的位置不会超出您的需要。
  • 请记住使用 C# using 构造

Since SqlConnection is sealed, you won't be able to inherit from it. (And I don't think it is a good idea to do so -- If it was possible, you should probably add your code in Dispose(false), because that is what the finalizer calls).

It is better to detect these kind of problems by using a static code analysis tool, which has the power to detect all places in your code where you forget to dispose a connection. There is one built in in Visual Studio, or you can use FxCop.

To help you not to forget disposing the connection, it is a good idea to:

  • Keep all DB connection code in one layer / assembly / module, so it is not scattered through the projects.
  • Have utility methods to perform SQL commands and returning the results; so you don't create SQLConnection more places than you need to.
  • Remember to utilize the C# using construct.
淡淡の花香 2024-09-14 04:00:05

一条经验法则是:“如果您必须考虑垃圾收集器,那么您可能做错了什么。” (当然,还有其他的拇指......)

在我看来,确保显式或通过 usingfinally 块关闭连接是最好的途径。

显然,您已经了解这些技术......所以也许一次浏览代码和可能的重构就是您所需要的。

One rule of thumb says, "If you have to think about the garbage collector, you're probably doing something wrong." (Of course, there are other thumbs...)

Seems to me that ensuring that connections are closed either explicitly or via using and finally blocks is the best route.

Obviously, you already understand these techniques... so maybe a once-through-the-code and a possible refactor is all you need.

东风软 2024-09-14 04:00:05

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

http://msdn.microsoft.com/en-us/library/8xx3tyca。 aspx

为了回答你的问题,我不相信有 GC 收集的事件,但是如果有也没关系,因为你永远不会知道 GC 是否选择在该收集过程中回收你的对象(并非所有由于分代算法,对象被清理)。

我还会避免尝试使用计时器和“检查”,因为您可能会保留对该对象的引用并防止其被处置。

If your application is using SQL Connection Pooling (the default) it will not matter since connections are re-used and don't get closed when you call .Close() or leave a using() {} block.

http://msdn.microsoft.com/en-us/library/8xx3tyca.aspx

To answer your question, I dont believe there is a event for GC collection, however it would not matter if there was, because you would never know if the GC chose to recycle your object on that collection pass (not all objects are cleaned because of the generational algorithm).

I would also avoid attempts to use timers and and "checks" as you will likely hold references to the object and prevent it from ever being disposed.

想念有你 2024-09-14 04:00:05

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

只需创建一个对虚拟对象的弱引用即可。如果稍后查看弱引用,该对象不再是 活着你也许可以假设发生了垃圾收集。

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

I am not very familiar with the garbage collector and don't know if there is a direct way to get the information but my first idea is the following one.

Just create a weak reference to a dummy object. If you look at the weak reference later and the object is no longer alive you can probably assume the a garbage collection occurred.

(This answer only applies to detecting garbage collector runs. I completely ignored the reason for doing this - there are much better strategies to deal with resource leaks.)

別甾虛僞 2024-09-14 04:00:05

首先,如果您正在考虑使用 GC,那么您就已经在某个地方遇到了严重的问题。我建议确保代码调用 Close 的最佳方法是使用 mocking。如果您的单元测试表明调用了 Close,则您的代码是正确的,并且您不必执行任何不必要的危险操作,例如使用垃圾收集器。

其次,如果您仍然坚持采用运行时检查路线,那么您唯一应该考虑做的事情就是挂钩 SqlConnectionStateChange 事件。例如,如果 ConnectionState 从 Open 更改为 Closed,则会触发该事件。

First, if you're even considering using the GC, you've got serious problems somewhere. I suggest that the best way to ensure your code calls Close is to unit test your code using techniques like mocking. If your unit test indicates that Close was called, your code is correct and you don't have to do anything unnecessarily dangerous like mucking around with the Garbage Collector.

Second, if you still insist on going the runtime checking route, the only thing you should even consider doing is hooking the StateChange event of SqlConnection. That'll fire if the ConnectionState changes from Open to Closed, for example.

爱冒险 2024-09-14 04:00:05

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

您无法控制这种行为。如果您的对象不再使用,它​​将自动被收集。为了阻止这种情况,你所能做的就是调用 GC.SuppressFinalize,但我不建议这样做,因为如果你忘记了,你就会被搞砸了。

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

If you forget to dispose, the object will be finalized. There is no way to control the time at which this happens, and there is also no way for you to know if an object is finalized. A seperate thread has to be created in order to finalized objects, so it slows your application down. That's why you want to dispose. In all classes in the framework that implement IDisposable, a call to GC.SuppressFinalize is made, so the object isn't finalized.

There is no way for you to controll this behaviour. If your object isn't used anymore, it will automatically be collected. All you can do to stop this, is call GC.SuppressFinalize, but I wouldn't recommend that, because if you then forgot, you'd be screwed for life.

You can create a wrapper class though (not a child class), that you use in your code that provides a few simple methods that always call Dispose. Otherwise, just check really well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文