views:

292

answers:

4

I am working to a VB.NET windows forms projet in .NET 1.1. And I have this type of architecture, very simplified.

Public MustInherit Class BaseTestLogic

  Private _TimerPoll As Timer

  Public Sub New(ByVal sym As SymbolFileMng, ByVal cfg As LampTestConfig, ByVal daas As DaasManager, ByVal mcf As Elux.Wg.Lpd.MCFs.VMCF)

    AddHandler _TimerPoll.Tick, AddressOf TimerPoll_Tick

  End Sub

End Class

Public Class SpecificTestLogic
  Inherits BaseTestLogic      

End Class

Depending of the type of test I am doing I create an instance of a specific test derived from BaseTestLogic. But I found that after hundreds of object creations I can have StackOverflow exception.

I checked my code and saw that I forgot to remove the handler to Timer Tick. The question is, where and when is it correct to remove hadler?

Do I need to implement the IDisposable interface in the base class and RemoveHandler in Dispose?

+1  A: 

If you add them in the constructor it would feel right to remove them in the Dispose, but it of course depends on your design.

Here is a question with information about when you need to worry about removing them
http://stackoverflow.com/questions/151303/addhandler-removehandler-not-disposing-correctly

ho1
I already read the linked question, but it didn't help much. I know that I should remove the handler but not sure where. Dispose could be an idea, I would like to be sure is the best practice.
marco.ragogna
Well one good reason to add them to Dispose in my view is that the user of your class can then use Using.
ho1
+1  A: 

You may go along with removing the handler when the Dispose is called, but a purist would say that "you shouldn't abuse IDisposable for purposes other than disposing unmanaged resources".

Another option is to remove the handler at the Finalize method.

You can also feel comfortable about removing the handler at several different places, if that makes any sense in your design. Removing an already removed handler will not cause any issue - unless the event is a Custom Event and its AddHandler/RemoveHandler implementations don't match the behavior of non-custom events (which is simply to use [Delegate].CombineDelegate/[Delegate].Remove). Just don't tell your purist friends about it; they won't comply.

M.A. Hanin
It is strange but in my case the finalizer is never called, what could be the reason?
marco.ragogna
The reason is probaby because some reachable object still holds a reference to the BaseTestLogic object or one of its members (event handlers included). An object is finalized only after there are no (strong) references to it (and the garbage collector decides it needs to remove the object).
M.A. Hanin
At the end I implemented the Disposable pattern and RemoveHandler to Tick event in the Dispose. The problem seems solved now. I am not a purist nor, luckily, colleagues that work with me :D
marco.ragogna
what M.A. Hainn is getting at, but not quite saying directly, is that if the Finalizer isn't being called you may already have a resource-leak (essentially the managed-version of a memory-leak). Tracking these down can be tricky and using a profiler can greatly assist, but they can seem like ghostly issues until you get a feel for what causes objects to live longer than they should.
STW
A: 

My first thought is that your actual problem has little, if anything, to do with adding and removing event handlers. A StackOverflowException means you have a series of functions that are creating an infinite loop of recursive calls. The code you posted does not show anywhere that could happen, but the stack trace of the exception should point you to the offending code.

Based on your comment about creating a test of a derived type, I wonder if you could post more of the code from the constructor in your base class.

Gideon Engelberth
@Gideon Engelberth: A StackOverflowException means that the stack is overflown. It is often because of an infinite loop / recursion, but that is simply because an infinite loop / recursion overflows the stack rapidly. Do note: they are not the same thing, and an infinite loop / recursion is not the meaning of a StackOverflow Exception.
M.A. Hanin
@M.A. Hanin: Perhaps I should have said "usually means", but whenever I see a stack overflow exception, I'm going to look for recursion since its by far the most common reason for such an exception.
Gideon Engelberth
A: 

It is strange but in my case the finalizer is never called, what could be the reason?

Or GC.SupressFinalize() has been called somewhere in your code?

Dib