GC and Dispose method questions

G

Guest

1) If I do want to keep an object alive throughout the live of an
application, how can I ensure that the GC doesn't clean it up?

2a) How do I determine if an object is a managed or an unmanged resource? I
understand the basic definition for managed resources are resources that the
CLR manage and unmanged resources are resources that the CLR doesn't manage,
however, I haven't been able to find a concrete answer as to what resources
are manage or not manage by the CLR.

2b) This is a following question to 2a. Are String and Int32 managed or
unmanaged resources (since it's not possible to do sTemp.dispose or
iTemp.dispose)? So does doing sTemp = Nothing or iTemp = Nothing release the
resource back to the memory?

3) I created serveral classes and I would like to be able to control when I
dispose it. I've found several articles regarding this topic and in each of
these discussion, the solution is exactly identical. Below is the sample from
the Microsoft MSDN website and is it true that all I need to do is customize
the code below in each of class? Is that the correct implementation?

Public Class Base
Implements IDisposable
' Implement IDisposable.
Public Overloads Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub

Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean)
If disposing Then
' Free other state (managed objects).
End If
' Free your own state (unmanaged objects).
' Set large fields to null.
End Sub

Protected Overrides Sub Finalize()
' Simply call Dispose(False).
Dispose(False)
End Sub
End Class
 
M

Mattias Sjögren

1) If I do want to keep an object alive throughout the live of an
application, how can I ensure that the GC doesn't clean it up?

You keep a reference to it that will not go out of scope, such as a
Shared field.

2a) How do I determine if an object is a managed or an unmanged resource?

If a class implements IDisposable it generally wraps some kind of
unmanaged resource.

2b) This is a following question to 2a. Are String and Int32 managed or
unmanaged resources (since it's not possible to do sTemp.dispose or
iTemp.dispose)?

They are managed.

So does doing sTemp = Nothing or iTemp = Nothing release the
resource back to the memory?

No, setting a String variable to Nothing just releases the reference
to the string object. If there are no other references to it the GC
will eventually clean it up.

Setting an Integer variable to Nothing is just the same as assigning
it zero.

3) I created serveral classes and I would like to be able to control when I
dispose it. I've found several articles regarding this topic and in each of
these discussion, the solution is exactly identical. Below is the sample from
the Microsoft MSDN website and is it true that all I need to do is customize
the code below in each of class? Is that the correct implementation?

Yes it looks like a good start.



Mattias
 
C

Cor Ligthert

Teresa,

When you do not use directly unmanaged resources yourself (API's) than there
would not be any reason to think about dispose or the GC at all when
Idisposable is implemented in a class.

When you use unmanaged resources yourself, you should use them implementing
IDisposable, from which I saw you has seen that already yourself.

http://msdn.microsoft.com/library/d...ref/html/frlrfsystemidisposableclasstopic.asp

I am not using dispose when there is told that Idisposable is implemented.
Except in some special situations where it seems for me that the dispose is
overloaded with extra stuff not really dispossing. By instance the
connection dispose, which takes care for connection pooling as well in Net
version 1x (this will be removed in 2.0).

An object is cleaned up by the GC when it has no reference anymore or when
there is not any reference anymore too it.

A string and integer are values, existing on the stacks. The live as long as
that stack part (method) lives (with the exception in vb of a static
variable, what is in fact global).

Just my thought,

Cor
 
A

AMoose

2a) How do I determine if an object is a managed or an unmanged resource?
I
understand the basic definition for managed resources are resources that the
CLR manage and unmanged resources are resources that the CLR doesn't manage,
however, I haven't been able to find a concrete answer as to what resources
are manage or not manage by the CLR.

I haven't found a way other than see if the object has implemented the
IDispose interface and sometimes just for kicks I look at IL just to see
what may be going on.

I *would* call the dispose method if implemented because leaving unmanaged
resources open can effect your program in different ways. Either that or
understand what the effect is of not calling dispose will have on your
program.

One effect is that unmanaged resources do not pressure the GC for collection
like managed objects do. The result is that you could end up with a lot of
unmanaged resources open, putting pressure on the OS. Of course they will be
cleaned up eventually but only when the GC deems it necessary and its basing
its decision on managed memory!

Example, take the following line of code and put it in a plain managed
windows application and make sure it runs on start up (in my example I made
sure F goes immediately out of scope and made sure there were no other
references to F):

- Dim F As IO.FileStream = IO.File.Open("somfile", IO.FileMode.Open,
IO.FileAccess.Write, IO.FileShare.None)

Now try to run a second instance of the application. On my machine I get an
exception. Go ahead and set F = Nothing and it continues to happen. I got
up, went to the bathroom, came back and tried to open a second instance
again and still got an exception (~2 minutes). FileStream has a handle to
the underlying unmanaged file and the code above is depending on the GC to
clean up the object. This situation would be catastrophic on a server
application processing many requests!
 
G

Guest

Thanks for everyone help!!!! I'm new to .NET and have a very tight deadline
on a .NET proj, I really appreciate all your quick responses.

I have two follow up questions...

1) If my class contains only string and integer members (no DB connection or
file or unmanaged objects), is it still good practice to have a dispose
method to set these member variables to nothing (for string) and 0 (for
integer)?

2) In AMoose's example, if I were to call the dispose (close) method for the
IO.FileStream object, F; then the problem you were talking about wouldn't
occur, correct?

Thank you again!!
 
C

Cor Ligthert

Teresa,

In my opinion

Never call dispose when it is not recommended, by instance for all Draw
objects and for connection.close.

Always close the things where there should be logical a "close" by instance
the file functions.
When you keep a file open by instance it stays locked and when you not
protect that an error will be thrown.

Just my thought,

Cor
 
A

AMoose

1) If my class contains only string and integer members (no DB connection
or
file or unmanaged objects), is it still good practice to have a dispose
method to set these member variables to nothing (for string) and 0 (for
integer)?

No. These are managed resources and they will be cleaned up by the GC when
they are unreachable. But if you had a filestream object as a member then
you would want to implement the IDispose pattern so that the underlying file
can be properly closed in time and not left open until the GC gets around to
it.

Its important to realize why IDispose exists, and its because of the
finalize method (the same one used in the IDispose pattern). Mainly the
finalize method exists so that you can be sure clean up of unmanaged
resources will take place and not left up only to the developer. The GC will
notice when an object implements finalize and will call it so resources will
be cleaned up. Unfortunately there are problems with finalize. You are not
sure when finalize will be called, and you have no control over it.
Implementing finalize will force the managed object to live longer. It puts
additional pressure on the GC. In some cases it may never be called. So in
the case of filestream example I showed this would be bad correct?

Also remember that unmanaged resources have no effect on the GC and when it
does garbage collections. Usually handles to unmanaged resources are 32 bits
and to the GC thats not a big deal. Unforunately to the operating system,
the resource in which that handle points to may be very "expensive". My
example shows that exactly. The GC saw no reason to clean up the filestream
object but in the mean time a file is held open and unusable to any
application that wants to use it. The only way for you the developer to
express the importance of that resource is to call Close(or in actuality
Dispose as explained later).

So IDispose exists as marker for objects that indicates to users of the
objects that they may want to call Dispose instead of waiting for the GC to
call finalize, and if the developer doesn't call Dispose the GC will call
finalize sometime in the future. Hopefully the documentation will tell you
enough about why IDispose is implemented and you can make a rational
decision whether to call it or not. If no documentation exists then you
will have to look at the IL or run it through Reflector to see whats going
on and then decide.

Of course whether you call Dispose or not can also depend on the type of
application you are building and the type of resource. I mostly work on
server applications and leaving unmanaged resources open any longer than
they have to be is a detrimental to performance and scalabilty. So "not
calling dispose" in most cases is not an option.

2) In AMoose's example, if I were to call the dispose (close) method for the
IO.FileStream object, F; then the problem you were talking about wouldn't
occur, correct?

Correct. And in actuality the filestream Close method is its Dispose method.
Here is the code for filestream's close method afer its run through
Reflector:

Public Overrides Sub Close()
Me.Dispose(True)
GC.nativeSuppressFinalize(Me)
End Sub

Looks familar doesn't it? Go back to your example or to the link Cor sent
you, Close *is* Dispose. So all you are doing with Close (or Dispose) is
deterministically cleaning up unmanaged resources and not waiting for the
GC. And in the example that I have shown waiting for the GC in some cases
can be "not good".
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top