2010-03-17 134 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