webForumDet fria alternativet

Dispose() metoden...

.NET

7 svar · 487 visningar · startad av fredrik

Medlem sedan dec. 19991 072 inlägg
Frågan#1

Tänkte bara höra och reda ut lite hur ni ser på "Dispose()" metoden....

Då jag vet att man inte ska lägga "viktiga" clean-ups i "_Terminate()" pga "non deterministic" GC så skapar man ju sig en "Dispose()" metod där man gör sin städning...

Men...ska man även lägga upprensning av "Managed code" i sin "Dispose", typ sätta objekt till Nothing och köra "Dispose"-metoder på de objekt man använt?

Vidare...ska man alltid kör "Dispose" på de objekt som har en sådan metod?

Ofta ser man att "Dispose()" är deklararerad som "Protected" i .NET klasser, varför? behöver de bara ropas på om man ärver från den klassen då? (det går inte annars antar jag....)

Tacksam för svar!

Medlem sedan maj 2001329 inlägg
#2

Själv har jag aldrig använt Dispose metoden förrän jag råkade ut för pooling problemet med SQL och jag skulle tro att det aldrig behövs om man inte använder unmanage code, men det överlåter jag till någon expert att svara på..

Angående varför den är protected är så enkelt att man i dispose skall kalla på dispose av basklassen.

En länk som kan skapa lite ljus..

Implementing a Dispose Method

wolly wolly

Medlem sedan apr. 20012 266 inlägg
#3

Detta är ätt rätt klurigt men intressant ämne. Men jag har för mig att mycket städas upp automatiskt vid slut av kodblock.

Ett exempel

dbObject dataLayer = new dbObject();
using(DataSet dataSet = dataLayer.RunProcedure("core_getSiteSettings", parameters, "Settings"))
{
  // kod #1
  // kod #2
}

vad jag förstår av detta är att när kod #2 är körd så körs alla dispose metoder på objecten som används inom using().

Medlem sedan aug. 2001458 inlägg
#4

renholm skrev:

...vad jag förstår av detta är att när kod #2 är körd så körs alla dispose metoder på objecten som används inom using().

Nästan. Ska man vara petig kan termen "...används..." bli lite fel. I exemplet nedan "används" ju foo, men kommer inte att dispose:as.

using (FileStream fs = foo.GetFileStream()) {/**/ }

Observera att using bara är språksyntax i C#. Det är precis samma sak som att göra try/finally och i finally-clausen anropa Dispose(). Andra språk än C# fungerar olika.

Jag rekommenderar artikeln här: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/dotnetperftechs.asp?frame=true. Den tar upp flera bra saker om Dispose och Finalize. Bland annat nämns destruktor-syntaxen som finns i C#, som i min mening inte borde finnas överhuvudtaget.

Fredrik, jag rekommenderar att du plöjer båda länkarna och återkommer om frågor kvarstår. Att sätta objekt till Nothing (eller null i C#) beror på det specifika fallet, men generellt sett ska du inte göra det.

> Vidare...ska man alltid kör "Dispose" på de objekt som har en sådan metod?
Ja. Om ett objekt implementerar Dispose är syftet att städa upp något. Ofta vill man explicit stänga en fil eller nätverks-anslutning så den inte hänger kvar öppen och blockerar samt tar systemresurser.

Dina frågor är högst relevanta, det är inte alls uppenbart hur Dispose och Finalize fungerar.

Medlem sedan dec. 19991 072 inlägg
#5

Tack för tips och länkar!

Jag har nu malt igenom texterna och det börjar klarna nu!

Att sätta objekt till Nothing (eller null i C#) beror på det specifika fallet, men generellt sett ska du inte göra det.

Ska man inte alltid sätta objekt till "nothing" (null)? För även om objektet inte kör någon dispose eller nån kod i Finalize() så måste man väl ändå tala om för "runtimen" att man är klar med objektet?

Medlem sedan maj 2001329 inlägg
#6

Det ska du inte behöva göra. När objektet trillar ur blocket eller inget pekar på det så användes det inte mer och det kan tas bort av GC:n.

Att inget pekar på det uppnår man bla med att sätta objektet till null. Och detta behövs ju enbart göras i specifika fall. Ex då man inte trillar ur blocket för att man har ett objekt som man håller i och detta objektet i sig pekar på ett andra väldigt stort objekt. Det kan då vara idee att sätta detta andra objektet till null för att frigöra minne.

Man kan väl även tillägga att det kan vara bra att sätta detta andra objekt till null även om det första trillar ur blocket. För det kan ju vara så att GC heapen enbart innehåller det första objektet och då 'ser' inte GC att detta objekt innehåller ett väldigt stort andra objekt och GC tror följaktligen att den inte behöver göra något för tillfället.

(Tillägg efter ännu en läsning av de bra länkarna som developer visade)

Fattade det nu som att problemet inte är när det hamnar ensamt i GC heapen som är det stora problemet istället är det när objektet hamnar i finalize kön och sitter där och väntar. DEt är då det håller massa stora onödiga minnesutrymmen.

Medlem sedan aug. 2001458 inlägg
#7

Grynet skrev:

Det ska du inte behöva göra. När objektet trillar ur blocket eller inget pekar på det så användes det inte mer och det kan tas bort av GC:n.

Kanske ett onödigt påpekande, men observera nyckelorden "kan tas bort". Det kan vara bra att veta att detta inte är helt sant om man kör under debuggern. Jag kommer inte ihåg detaljerna som skiljer (hittade inte artikeln jag läste det i), men debuggern kan hålla referenser lite längre än om programmet körs stand-alone.

För den som vill läsa mer om hur GC fungerar i .Net finns 2 bra artiklar av Jeffrey Richter om detta:
- http://msdn.microsoft.com/msdnmag/issues/1100/GCI/GCI.asp
- http://msdn.microsoft.com/msdnmag/issues/1200/GCI2/GCI2.asp

När jag ändå är i farten, vill jag rekommendera Brian Harry's artikel "Resource Management", som beskriver bakgrunden till varför .Net har en garbage collector (till skillnad från referensräkning) och hur funderingarna gått under utvecklingen.

Medlem sedan dec. 19991 072 inlägg
#8

Ok, tack för alla tips!

En sista fråga då...Vad är skillnaden mellan att sätta ett objekt till Nothing (null) och att inte göra det? Kommer inte resultatet att bli samma sak? dvs. när objektet går ur blocket (eller när det sätts till Nothing) så kör GC "Finalize" om det finns någon.

Alltså att GC gör samma sak oavsett om man manuellt sätter objektet till Nothing eller om man låter det gå ur blocket självt.

Var nämligen på kurs för inte så länge sen (http://www.learningtree.co.uk/ilt/courses/uk503.htm) och instruktören hävdade att man alltid skulle sätta objekt till Nothing...Därav min envishet! :)

262 ms totalt · 3 externa anrop · v20260731065814-full.767b4345
123 ms — deklarationer (db)
0 ms — hämta statistik (cache)
136 ms — hämta tråd, inlägg och bilagor (db)