views:

176

answers:

5

Hello All,

I have a third party component I'm using and I'm seeing some issues with resources not being released. The component causes windows to create a handle to a UDP socket ("\Device\Udp" as well as "\Device\Afd"). If I allow the program to execute and dereference the third party object, I assumed that like all .NET objects I've worked with in the past, the object will get garbage collected. However, Process Explorer is showing that the "\Device\Udp" handles are being kept indefinitely until the actual process is killed (or in the case of the app in question: app pool is recycled.

Furthermore, if I manually call the Dispose() method of the object, then the handles are released. This is the fix I have in place, but I'm just curious about why it is needed. Is it possible that the builders of the componenet have done something or set some attribute which prevents the garbage collector from calling the destructing on the object?

If it helps, I have posted the code below. The code was used in a Forms application, so the process does not end after the while loop completes.

Code that does not work (100 handles created indefinitely):

        for (int i = 0; i < n; i++)
        {
            Snmpmgr mgr = new Snmpmgr();
            mgr.Timeout = 10;

            mgr.ObjCount = 1;
            mgr.ObjId[1] = ".1.3.6.1.2.1.1.1.0";

            try
            {
                mgr.SendGetRequest();  // Handle shows up in ProcExplorer after this call
            }
            catch (Exception ex)
            {
                throw new TimeoutException("Error contacting CMTS.");
            }
        }  // end of for...  obj referenced by mgr never garbage collected

Code that does work (handles created and released):

        for (int i = 0; i < n; i++)
        {
            Snmpmgr mgr = new Snmpmgr();
            mgr.Timeout = 10;

            mgr.ObjCount = 1;
            mgr.ObjId[1] = ".1.3.6.1.2.1.1.1.0";

            try
            {
                mgr.SendGetRequest();  // Handle shows up in ProcExplorer after this 
            }
            catch (Exception ex)
            {
                throw new TimeoutException("Error contacting CMTS.");
            }
            mgr.Dispose();  // UDP Socket Handle freed...  not sure that's how to spell free + ed :)
        }

Thanks in advance for your help.

Chris

+5  A: 

You used a mgr.Dispose call in the second example. I'll take it mgr is an IDisposable?

In that case, you need to use a using block:

for (int i = 0; i < n; i++)
{
    using(Snmpmgr mgr = new Snmpmgr())
    {
        // Your Code
    }
}
MiffTheFox
Good suggestion. I failed to remember the using statement, which does the same as my code above, except the call to Dispose() is created via compiler rather than in my code, right? +1 for optimizing my pseudo code. However, in my production environment, the Snmpmgr is a global var in the Page class (since it is used multiple times via button click events, and load events), so I don't really have the option to Dispose directly after use (unless I want to recreate the object on 15 different occasions). Sorry I did not mention that in my original post.
regex
A using block in not *needed*. It's probably a good idea, but it's not necessary. Calling Dispose will accomplish the same thing, though the call to Dispose should probably be in a finally block.
Todd Ropog
If you don't want to dispose of the object after each use, then you need to make sure it gets disposed of at some point. If there's a reliable point at which you can do this then that would work. However, it's generally a recommended practice to dispose of things as soon as it makes sense to do so. So make sure you aren't holding on to the object longer than you should. Think carefully about this.
Todd Ropog
I presume I will call the Dispose() at the end of the Page's life cycle then... Argh... I can never remember the Page's final event off hand... unload maybe? Anyway, off to Google :) Thanks for all the tips. I will look into creating a new object every time I want to use that function since everyone seems to recommend that is better practice.
regex
+2  A: 

Calling Dispose is the proper thing to do. Some objects use unmanaged resources (and if you're working with sockets, it's likely the case). The Dispose method is exposed precisely so that the object can properly deallocate its unmanaged resources. Any time you use an object that implements IDisposable, you should call Dispose when you're done with it.

For more detail about IDisposable: http://stackoverflow.com/questions/12368/how-to-dispose-a-class-in-net

Todd Ropog
+3  A: 

That's the point about the Dipose() method. Since one can never know when the destructor will be called, you should use Dispose to release unmanaged resources. As MiffTheFox said, you should put your code inside an 'using' block. When the code execution reaches the end of the 'using' block, Dipose() will be called automatically.

Fernando
+1  A: 

Perhaps you can put mgr.Dispose() in your "finally" clause, after your try/catch block.

janetsmith
A: 

You did in fact implement a destructor on the Snmpmgr class to release the socket handle, right? ... otherwise the GC does not know there is some work to be done to release resources if you do not do it explicitly through Dispose().

jerryjvl