2009-12-23 65 views
0

我有以下代碼片段,只是想檢查誰會調用dispose?它是否自動調用。C#內存和處理相關問題

ToolTip toolTip = new ToolTip(); 
toolTip.SetToolTip(button, toolTipText); 

也讓說,我創建一個定時器局部變量,誰就會調用Dispose,那內存泄漏,因爲,如果我調用Dispose馬上,定時器事件,不會被解僱。

我是否需要確保在計時器事件處理程序中調用dispose,即使我沒有任何對計時器變量的引用。我也需要註銷該計時器的事件處理程序。

編輯:

  • 但如何調用Dispose工具提示,如果我把它不會顯示。
  • 此外,爲什麼我需要配置定時器,如果我沒有任何參考。
  • 我是否還需要註銷定時器事件處理程序?
  • 還有一個引用會增加類的內存佔用。

回答

1

在.NET中,當一個對象不能從任何地方被引用時,垃圾收集器將自動釋放內存。當它這樣做時,如果對象有終結器,它會調用終結器。終結者是爲了清理,通常是非託管資源。但是,終結器是昂貴的(例如,它們會延遲對象上的垃圾回收),並且無法確定它何時運行(因爲無法判斷GC什麼時候會決定收集它)。他們通常被留作清理非託管資源之類的最後手段。

這是IDisposable接口和它的Dispose方法進來的地方。Dispose也可以用來清理託管和非託管資源。當您調用Dispose方法時,它將清除並且對象不再處於穩定的可用狀態。

如果您有一個實現IDisposable的資源,您可以在知道完成後調用Dispose。它所持有的這種方式和資源可以儘快釋放出來。這樣做的通常方法是將其封裝在using語句中,當using塊完成時它將自動Dispose。例如:

using (SomeDisposableObject disposableObject = new SomeDisposableObject()) 
{ 
    disposableObject.DoSomeStuff(); 
    disposableObject.DoSomeMoreStuff(); 
} 

當使用塊完成時(在DoMoreStuff之後)DisposeObject上調用Dispose。在考慮異常處理時,使用語句比等效代碼清晰得多。

對於像ToolTip這樣的非託管引用(非託管Win32組件中包含很多WinForms)的情況,它將會有一個終結器來確保正確釋放未被佔用的資源。但是,如果您在對象上調用Dispose,則會在該處運行清理代碼,然後禁用終結器(當GC收集對象時它不會運行)。

因此,要直接回答您的問題,如果您確切知道IDisposable何時完成,則最好調用Dispose。但是,如果您不這樣做,通常只需將其留給垃圾收集器來收集並調用相關代碼即可正確清理該對象。

在給出ToolTip和Timer的情況下,我不會擔心自己調用Dispose,因爲我懷疑它很難預測什麼時候會完成。

+0

這樣做很有意義,不必要的預訂會使代碼複雜化並在調用GC之前實現少量字節的減少。但是如何確保對象不需要手動處理,其他職位的人說你需要調用Dispose表單相關的對象,因爲他們有HWND等。 –

+0

如果可以,請調用Dispose來清理HWND等等。但是,如果你不知道終結者應該爲你清理它。不知道如何與意想不到的應用程序退出等事情相符。希望有更多合格的人可以詳細說明。 – ICR

0

一般來說,它取決於註冊到事件的對象註銷 - 不這樣做會造成內存泄漏。你不應該依賴這樣做的Dispose方法。除非將對象封裝在using(){}語句中,否則將其添加到對象IContainer實例(如果它是設計器類),Dispose不會自動調用。如果它是一個類變量,則需要使包含的類實現IDisposable並處理其中的實例。

+0

你的回答不清楚,你的意思是說我需要不必要地引用計時器,然後取消註冊事件處理程序然後處置它? –

+0

是的 - 你需要保持一個引用,然後取消註冊事件,當它被處置 – thecoop

+0

我猜.NET的垃圾收集器會自動GC,如果沒有引用,它可能需要一些額外的時間,但調用Dispose不是強制性的,註冊事件處理程序並調用處理並取消註冊事件處理程序是沒有意義的。 –

2

Dispose是一種允許您立即釋放對象的方法。例如專用文件流。

Finalize是一種方法,可以在程序不再使用對象時自動釋放對象正在使用的任何資源。

當對象使用獨佔或有限資源時,您只需要考慮處置。示例是文件1或數據庫連接。 (請注意,在這兩種情況下,Close都相當於處置)

要回答你的問題,你根本沒有進行處理,而是讓終結器在需要時運行。

+1

WinForms控件和組件實現IDisposable(因爲它們確實擁有像HWND或定時器句柄這樣的有限資源),因此應該進行處理而不是等待finaliser。 – itowlson

+0

但是,我應該擔心保持參考和處置,或讓終結者完成這項工作。此外,保持引用會增加類內存佔用量。 –

+1

保留一個引用會將類內存佔用量增加幾個字節。但是這個類是Windows窗體,是嗎?除非你期望創建數十萬個表單實例,否則一個額外引用的內存開銷就會變得微不足道 - 只是不值得擔心! – itowlson

1

你需要調用Dispose來實現IDisposable的任何事情,或者至少確定一些事情。對於UI組件,將它們添加到表單的Controls集合中,當表單關閉時它們將被丟棄。對於其他事情,您需要保留對它們的引用並適當調用處置。讓您的類實現IDisposable只是爲了在您的組合對象上調用Dispose。

+0

我不同意,爲什麼不必要的保持引用,看看我在編輯問題。 –

+0

如果您滿足在最終確定期間釋放的資源(垃圾收集時間),則不需要__need__來調用Dispose()。 –

+0

您保留(相對)便宜的參考,以便您可以避免(相對)稀少或昂貴的資源。 –

6

ToolTip將事件處理程序註冊到顯示它的控件上。它的Hide()方法在窗體的Deactivate事件觸發時自動調用。當表單關閉時會發生這種情況。這反過來確保其Windows句柄被銷燬並且事件處理程序未註冊。之後,還沒有剩下的一次性物品。

您可以使用Reflector或Reference Source來驗證這一點。相關方法依次爲BaseFormDeactivate,HideAllToolTips,Hide,ClearTopLevelControlEvents。

你不必調用Dispose(),你沒有泄漏。

+0

這裏完全困惑,你說不需要,其他職位的人說需要。另外如果我沒有任何對timer類的引用,它會在事件被觸發後自動進行GC嗎? –

+0

我不認爲他們看代碼。如果沒有引用留給它,每個非靜態對象都進行GC編輯。 –