2010-03-17 125 views
11

很久以前,我从C/C++开始,我仍然有一个确保所有资源都被正确清理的习惯。我总是确保在IDisposable类上调用Dispose,并在包含一次性对象的类中实现Dispose模式。IDisposable,它真的很重要吗

但是,在我的环境中,我或多或少是唯一这样做的人。其他人只是不明白我在做什么,认为我的代码更难理解。

他们只是创建数据库连接,打开流等没有调用关闭或处置。有时他们会在方法的末尾设置一个局部或成员变量为“Nothing”(猜测他们的背景)。

我的问题是他们的代码和我的一样好。代码随着时间的推移会创建数千个数据库连接对象。

因此,忽略任何关于代码正确性的论点,遵循指导原则等,IDiposable真的很重要

有没有人从废弃的物品中耗尽了资源?

编辑: 感谢您的回复。有趣的是,看到有些人在不处置时有问题。这似乎很少见,但我认为GC/JIT在正常情况下保持资源使用情况良好。

我的同事和我都不会因为这个而改变行为,但是感觉很好。

+1

关于SO的许多问题都是“奇怪的东西发生”变种。我发现其中大约一半是由于未能处置而导致的,特别是如果它们只是通过某种循环发生第二次或随后的时间。另一半是未处理的例外,顺便说一句。 – 2010-03-17 20:00:13

+0

我已经与其他人一样使用IDisposible模式并收到了类似的反应。在这场冲突中你当然并不孤单。我恳求你不要妥协,因为你的代码“难以阅读”。只是我2美分。 – 2010-03-17 20:04:43

+2

如果没有别的,__explicit__永远比隐式更好,不管语言如何 – 2010-03-17 20:07:48

回答

26

是的,当循环连接对象时,我已经清除了Oracle游标的数量,例如,因为我忘记关闭命令阅读器 - 在单个连接上也只有100个循环,我需要支持可能有数百个连接同时进行。

如果您不想让自己关闭任何非托管资源,应该教会您的开发伙伴使用using() { ... } syntax。无论如何,这是一个很好的练习,你也应该使用它,因为你自己可能忘记将你的Dispose()调用放在finally {}子句中,以便在发生未处理的异常时真正清除。

如果你不能赢得他们的心 - 改变他们的想法 - 创建测试,通过最大化他们没有清理的资源来破坏他们的代码 - 然后显示“修复”是简单和容易的,并且使他们的代码更具可扩展性。或者只是将它展示给你的老板,告诉他们这将使他/她能够将产品作为新版本销售,并具有更高的可扩展性:)希望你的开发人员能够在将来一直这样做,并希望你也会受到更高的关注。

+4

用于编写测试以打破不好的练习。 – 2010-03-17 19:54:30

1

不处置(或关闭)数据库连接最终会咬你,是的。我见过这种情况。

+0

@ Anon-Downvoter “有没有人从没有处置的对象中耗尽了资源?” 我的回答是对这个问题的直接回答,不需要散文,至少可以解释你有缺陷的推理。 – heisenberg 2010-03-17 20:11:35

4

其中一些资源(如句柄)是整个系统的有限资源,所以如果您的应用程序不释放这些其他应用程序,甚至操作系统可能会受到影响。例如,请看Mark Russinovich的latest article以推动Windows系列的极限。

0

我有一个情况,我不幸记不清细节,但它是某种分层流。在上层文本格式化程序刷新之前,较低级文件流有时会关闭,导致写入文本格式化程序的最后输出丢失。

3

是的,我也遇到了连接对象到Oracle数据库没有被处置的问题。

迈克阿特拉斯的上述问题很糟糕,但至少清楚发生了什么问题。我们碰到的问题是,在重负载的情况下,当我们试图打开连接时,网站会开始抛出错误,但当我们查看系统时,它已经全部清除了(因为garabe收集器已经清除对象并释放连接池)。这是很难复制,直到我查看代码,并注意到一个错误的情况下没有关闭连接,将此更改为一个using声明修复了整个问题。

简短的回答是,如果一个对象需要努力实现IDisposable,那就是出于某种原因,所以总是在完成时处理它,理想情况下使用using声明。不要因为有时处置而聪明或棘手,但在其他情况下,如果你不认为你需要这样做,那么就不要这么做了。只要做到每一次都有效。

更短,更令人满意的答案是,你是对的,你的同事是不知道他们在做什么的白痴。

5

是的,它很重要。当一个对象实现IDisposable时,它明确地是,指出它在持有不再需要对象时需要释放的资源。

当对象完成时,大多数仍然会清理它们的资源,但最终确定并非确定性的,并且不能用于资源管理。

只需将变量声明包装在using(...)块中,便于正确处置。

0

不配置数据库相关的IDisposable对象是在环境中生成OutOfMemoryExceptions的可靠且有效的方法。

DataSet实现了IDisposable,我读过它没有必要调用Dispose,因为需要为数据集处理的对象仅在设计时(由Visual Studio设计器创建)创建。我从来没有见过来自未处理数据集的OOM(仅来自庞大数据集的OOM)

0

除了资源耗尽的明显情况(已经提到)之外,IDisposable的另一个好处是,由于它确保Dispose()当using模块退出时调用,您可以将其用于各种事物,甚至不仅仅是“用OS资源执行操作”。

以这种方式,它就像一个穷人替代Ruby块,或者一个小的Lisp宏用例。

0

是的,是的,是的,,重要。

我一直在分析最近从未分析过的应用程序。这只是一个Winforms应用程序,没什么大不了的,对吧?

错误。

由于没有实现IDisposible而没有取消引用事件处理程序,因此应用程序像筛子一样泄漏内存。

.NET Framework并不免除你自己清理后,它只是使它不太可能破坏某些东西,如果你没有。

花一个小时,用ANTS Profiler描述您的应用程序。这是一个免费试用版。如果你没有看到任何内存泄漏,那么继续前进。如果你这样做,那是因为你依靠.NET Framework来成为你的拐杖。

+0

我知道这个理论,但是在桌面上存在漏洞真的是一个大问题? (服务器应用程序是另一回事) 使用千兆字节的RAM可能需要很长时间才会影响性能。 – adrianm 2010-03-20 21:10:30

+1

是的,它很重要。如果您有一个多处理桌面应用程序没有处置,它所拥有的任何数据也会保持活动状态。所有用户所要做的就是使用你的应用程序,因为内存在磁盘上分页和分页时会变得越来越慢。如果你不关心你的应用程序,那很好。让我知道它是哪一个,所以我不买它。 – 2010-03-21 17:53:30