views:

128

answers:

2

Ok,

So I have a method which fires when someone clicks on our Icon in a silverlight application, seen below:

    private void Logo_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        e.Handled = true;
        ShowInfo(true);

        DispatcherTimer autoCloseTimer = new DispatcherTimer();
        autoCloseTimer.Interval = new TimeSpan(0, 0, 10);
        autoCloseTimer.Tick +=new EventHandler((timerSender,args) => 
            {
                autoCloseTimer.Stop();
                ShowInfo(false);
            });
        autoCloseTimer.Start();
    }

Whats meant to happen is that the method ShowInfo() opens up a box with the company info in and the dispatch timer auto closes it after said timespan. And this all works...

But what I'm not sure about is because the dispatch timer is a local var, after the Logo_MouseLeftButtonUp method finishes, what is there to keep the dispatch timer referenced and not availible for GC collection before the anonymous method is fired?

Is it the reference to the ShowInfo() method in the anonymous method?

Just feels like some thing I should understand deeper as I can imagine with using events etc it can be very easy to create a leak with something like this.

Hope this all makes sense!

Andy.

+8  A: 

The DispatcherTimer registers itself with the Dispatcher by calling the internal Dispatcher.AddTimer method when you call Start.

Since it also unregisters itself by calling Dispatcher.RemoveTimer when you call Stop, you won't leak memory.

The Timer keeps the anonymous method alive in its Tick event, which also keeps the variables in the method alive through the closure.

SLaks
Ah, cool, thanks! Guess I should have really reflected it instead of being lazy! :)
Andy
@Andy: You should also accept answers to your questions.
Adam Robinson
Which I was going to do! lol, just though it was nice to give feedback also!
Andy
@SLaks: isn't it also so that the timer is kept alive by the event handler that is attached to the `Tick` event? I would believe that as long as the `Tick` event handler is not detached, this will prevent GC from collecting the timer.
Fredrik Mörk
@Fredrik: No. The timer references the event. The event does not reference the timer. (In this case, it does, via the closure, but that's irrelevant because nothing else references the event)
SLaks
@SLaks: ah, yes you are right. I don't understand why I can't get my head to get that. I know there is something about that relation, and I consistently get it the wrong way around.
Fredrik Mörk
@Fredrik: It's very simple. An event is a field containing a delegate that holds zero or more methods. Each method delegate has a reference to the target that the delegate gets invoked on. The method itself is not aware that it's been bound to an event.
SLaks
Yes, I am aware of that. It's just that at some point when I think about events, I get it the other way around. It's a bit funny, especially given that I have been digging into events rather deeply in order to write a blog post about their inner workings. Embarrasing, really ;)
Fredrik Mörk
+1  A: 

One of the more obscure causes of memory leaks in .NET is event handlers. An event handler is a reference to an object, and keeps the object in scope. When you're done with an event handler, it needs to be dropped. If the event handler is used only once, it can deregister itself, but if it gets used more than once, there will need to be some other object that knows when it's no longer useful, and drops the event handler.

Cylon Cat