Sök på tekniken.nu

Om tekniken.nu

På tekniken.nu bloggar Iteams konsulter om det som ligger dem varmast om hjärtat - teknik.
www.iteam.se

Prenumerera på tekniken.nu

Bloggportalen.se
Bloggtoppen.se
Top Datorer bloggar
Web Analytics

Clicky

En självklarhet!
Teknikbloggen logotype

Se upp med eventhanterare som pekar på lagrade objekt

2007-11-19 09:13 - Utvecklingstips av Erik Hjortsberg
Erik Hjortsberg
Erik Hjortsberg
Systemutvecklare
Iteam
Garbage Collector

En intressant liten artikel (egentligen förtäckt reklam för en produkt, men låt gå) om ett gäng som skrivit kod i C# för att styra en förarlös bil i The Darpa Challenge: http://www.codeproject.com/showcase/IfOnlyWedUsedANTSProfiler.asp

Det här är samma sak som vi själva upptäckte för något år sedan (men aldrig bloggade om): om objekt1 lyssnar på events från objekt2 kan objekt1 inte tas bort av garbage collectorn förrän objekt2 också tas bort - eftersom de har en stark koppling. Ett fall där detta kan inträffa i ASP.NET är om man har objekt i Session som genererar events, som man låter webbkontroller lyssna på. Då kommer webbkontrollen att ligga kvar i minnet även efter att sidan laddats ur (då de normalt städas bort).

En fin lösning på det här problemet är att använda svaga referenser, som t.ex. finns inbyggt i Smalltalk: http://www.haible.de/bruno/papers/cs/weak/WeakDatastructures-writeup.html.
.NET har en WeakReference-klass, http://msdn2.microsoft.com/en-us/library/system.weakreference.aspx, men jag har aldrig sett den användas någonstans. Framförallt inte på events.

Så det rätta att göra i .NET för att undvika det här är att alltid se till att städa upp sina event-listeners. Det som gör det lite ointuitivt är att i alla exempel från Microsoft så sparas aldrig någon referens till eventlyssnarna, så det går inte att ta bort dem. Så här brukar det se ut:

foo.AnEvent += new EventHandler(AMethod);

dvs. man skapar upp ett EventHandler-objekt som man sen kopplar men inte har någon annan referens till. På så sätt så har man sen ingen möjlighet att ta bort kopplingen. I 99% av fallen vad gäller t.ex. webbsidor så gör det inget - allt tas ändå bort av sig självt när webbförfrågan är över. Men om man nu vill ta bort lyssnaren på ett fint sätt så måste man istället göra såhär:

EventHandler anEventHandler = new EventHandler(AMethod);
foo.AnEvent += anEventHandler;
/* .... massor av kod etc... */
foo.AnEvent -= anEventHandler;

När man gör foo.AnEvent -= anEventHandler så tar man bort referensen till this ifrån foo, vilket gör att this inte har några starka referenser och kan städas bort ur minnet som vanligt.

... och du vet väl att Iteam just nu söker duktiga medarbetare? Läs mer på iteam.se

Andra bloggar om:
Inga kommentarer

Kommentera

Namn

Email

URL

Kommentar

Skriv vad som står i bilden till höger