views:

127

answers:

1

Hi.

I'm fixing a User control component using the .NET 1.1 framework.

There are many instances of this user control referencing a singleton wrapping a COM resource. They subscribe to events from this resource.

I suspect that the reason why we are having a degrading performance is because the singleton is maintaining a reference to the user control classes even after their respective windows are gone. Thus preventing GC.

They unsubscribe the event in their finalize method. Hence I suspect a chicken and egg problem. The finalize wont execute because they are being referenced through their event subscription in the longer lived Singleton, preventing GC.

Where in a User Control should I perform the event unsubscribe to make it eligible for GC?

I do not own the application hosting the user control.

+1  A: 

You should unsubscribe when the control is disposed, really. If you can't easily modify the Dispose method yourself, you could add an event handler to the Disposed event:

ComSingleton.Foo += FooHandler;
this.Disposed += delegate { ComSingleton.Foo -= FooHandler; };

If you want to subscribe to events using anonymous methods or lambda expressions, you'll need to use a separate local variable so that you can refer to it again:

EventHandler tmp = delegate { Console.WriteLine("Something happened"); };
ComSingleton.Foo += tmp;
this.Disposed += delegate { ComSingleton.Foo -= tmp; };

An alternative is to use "weak event handlers" - there are many articles about this on the web; here's one which goes into a fair amount of detail.

Jon Skeet
Woa. THE Jon Skeet. I'll just tag for "correct answer" and then try it :) Thank you
Tormod
I have made a simple winform, a singleton with an event and a user control. The user control subscribes to the singleton event in its load method and retains the delegate instance in a member variable to run -= in the dispose method. However, the breakpoint in the finalize method is never executed.I also have tried to set the Usercontrol reference in the Winform to null with and without calling dispose() on it first. The user control object does not appear to be finalized even when it is no longer referenced by the winform or the singleton. Am I on the wrong track?
Tormod
My way of testing the solution is definitely flawed. I cannot break within or receive trace from the Finalizer even after I stopped referencing the Singleton.
Tormod