Confused about GC & Disposing: How to get it right?

G

Guest

Hi,

I have read alot on Disposing and Garbage collecting and I am still
confused about how to get it right. I use Frameword 1.1, VB.Net and I need
to understand the best practices concerning the following issues.

Let's start at the beginning: I need to know what to do when I have a
class that uses instances of objects that have the dispose method, let's say
third party Menu objects.

1) Should I bother about disposing at all? I read that I should, but a
confirmation would be great. Instinctively, I would rather develop an
application that disposes of the objects it creates as soon as possible. Am
I right in assuming this?

2) Should I use the Dispose Design Pattern on my class to dispose of a Menu
object? Should I conclude that every class that owns resources that have the
dispose method should also use the Dispose Design Pattern? Or should I
dispose of the menu instances directly in the finalize instead?

3) Could you give an example of a typical class that uses Disposable object
instances that would teach me how I should dispose of them?

4) As for the Dispose Design Pattern, what is the difference between managed
and managed resources? Is there some rule of thumb I should be using to
differenciate between the two? Is it that Unmanaged resources have a dispose
method and Managed resources don't?
In the Dispose Design Pattern, there is this method:
Protected Overloads Overridable Sub Dispose(disposing As Boolean)
' Check to see if Dispose has already been called.
If Not (Me.disposed) Then
' If disposing equals true, dispose all managed and unmanaged
resources.
If (disposing) Then
' Dispose managed resources.
End If
' Release unmanaged resources.
Me.disposed = true
End If
End Sub
Where would I call
a) myMenu.dispose
b) myArrayList.clear
c) myDataSet.dispose and/or myDataSet.Close

5) I use ArrayLists in my classes. These ArrayLists may contain objects
that have a disposable method. How and where should I dispose of them? Will
calling the clear method dispose of these objects for me? I have created an
ArrayList subclass that looks like this:
Public Class DisposableArrayList
Inherits ArrayList
Protected Overrides Sub Finalize()
Try
Dispose(False)
Catch
'TODO: Send to console
Finally
MyBase.Finalize()
End Try
End Sub
Public Overloads Sub Dispose() Implements System.IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean)
If Not (_Disposed) Then
If (disposing) Then
DisposeItems()
End If

_Disposed = True
End If
End Sub
public Sub DisposeItems()
Dim item As Object
Dim disposableItem As System.IDisposable
Dim iterator As System.Collections.IEnumerator
Dim oef As Boolean

iterator = MyBase.GetEnumerator

Do
oef = Not iterator.MoveNext()

If oef Then
Exit Do
Else
item = iterator.Current

If TypeOf item Is System.IDisposable Then
disposableItem = CType(item, System.IDisposable)
disposableItem.Dispose()
End If
End If
Loop

MyBase.Clear()

iterator = Nothing
disposableItem = Nothing
item = Nothing
End Sub
End Class
Is that a good way to do it?

Thanks for de-confusing me up,

E. Thouin
 
A

Alvin Bruney [MVP]

Get Richter's book. It will teach you a lot more than just disposing. In
fact, you should have it in your library anyway.
 
S

Scott M.

I think the key to understanding if you need to call dispose is to
understand managed vs. unmanaged resources.

If something is "managed", then the .NET Framework CLR (common language
runtime) is in charge of its processing. So, a .NET Connection object is
managed, for example. The CLR can determine when a connection object is no
longer referenced and is in complete control over its memory allocation.

Now, here is the tricky part, while the .NET Connection *object* is managed,
the database connection it has established is NOT. The database is not a
CLR managed resource. So, if the CLR removes the connection object from
memory without the .NET connection object closing the DB connection, then
the DB will wind up having a locked connection that no one else can use

..NET objects that use unmanaged resources (things that the CLR does not
control) like a connection object, typically expose a dispose method and in
that method, you can provide "clean up" code to clean up those unmanged
resources. In a connection object's dipose method, you could call the
connection object's .Close method to essentially disconnect from the data
source that the connection was connected to.

Not all objects have, nor do they need, a dispose method. Generally, you
need dispose if the object uses unmanaged resources and you want a place to
clean up those resources when the object is done doing its job. Since we
don't know when Finalize will run (or theoretically even "if Finalize will
run), it is not generally a good idea to write clean up code there, but you
can call an object's Dispose method yourself.
 
G

Guest

So, given what you said,

1) Where should I put the line "myMenu.dispose" in a class that owns the
myMenu instance?
2) Where should I put the line "myConnection.dispose" in a class that owns
the myConnection instance?

In Finalize() or do I use the iDisposable mecanism?
 
R

Richard Blewett [DevelopMentor]

Implement IDisposable yourself. You must not call other objects in your Finalize method. The order in which a group of objects that have references to eachother is not determines. You may be calling Dispose on an object that has aloready been Finalized.

Regards

Richard Blewett - DevelopMentor
http://www.dotnetconsult.co.uk/weblog
http://www.dotnetconsult.co.uk

nntp://news.microsoft.com/microsoft.public.dotnet.framework/<[email protected]>

So, given what you said,

1) Where should I put the line "myMenu.dispose" in a class that owns the
myMenu instance?
2) Where should I put the line "myConnection.dispose" in a class that owns
the myConnection instance?

In Finalize() or do I use the iDisposable mecanism?
 
G

Guest

So can I conclude that
a) Each class that owns disposable objects should itself implement
IDisposable to dispose of these objects
b) Objects that at some point used unmanaged resources have a dispose method

My remaining questions:

1) When I have an arraylist of disposable objects, do I need to parse the
arraylist to dispose all of its items? Can myArrayList.clear do the trick?

2) Do I overload the Dispose Design Pattern dispose method correctly here:
Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean)
If Not _Disposed Then
If disposing Then
'Unmanaged resources
myMenu.Dispose()
End If

'Managed resources
myMenu = Nothing

_Disposed = True
End If
End Sub

Thanks
E.Thouin
 
S

Scott M.

1) Where should I put the line "myMenu.dispose" in a class that owns the
myMenu instance?

As soon as you are done with the myMenu object and the resources it is
controlling.
2) Where should I put the line "myConnection.dispose" in a class that owns
the myConnection instance?

As soon as you are done with the myConnectionobject and the resources it is
controlling.
In Finalize() or do I use the iDisposable mecanism?

Finalize is the last thing to happen to an object. Finalize happens after
Dispose.
 
S

Scott M.

Conceptor said:
So can I conclude that
a) Each class that owns disposable objects should itself implement
IDisposable to dispose of these objects

Not necessarially. The class that owns disposable objects would call the
dispose method of the "child" objects so there would not necessarially be a
need for the "parent" class to have a dispose method.
b) Objects that at some point used unmanaged resources have a dispose
method

They should, but if we are talking about a custom class, you have to build
it yourself (unless you are inheriting from a class that already exposes a
dispos method, such as a component class.
My remaining questions:

1) When I have an arraylist of disposable objects, do I need to parse the
arraylist to dispose all of its items? Can myArrayList.clear do the
trick?

I don't know as I haven't used arraylists very much, but my gut tells me
that .clear does not dispose the members of the arraylist.
 
R

Richard Blewett [DevelopMentor]

1) You'll have to walk the list, Clear just empties the ArrayList, tnothing else.

2) Thjis is more tricky. You need to show the implementation of IDisposable.Dispose and Finalize as well. At a first look its not right, but to give you complete feedback you need to show the other two methods

Regards

Richard Blewett - DevelopMentor
http://www.dotnetconsult.co.uk/weblog
http://www.dotnetconsult.co.uk

nntp://news.microsoft.com/microsoft.public.dotnet.framework/<[email protected]>

So can I conclude that
a) Each class that owns disposable objects should itself implement
IDisposable to dispose of these objects
b) Objects that at some point used unmanaged resources have a dispose method

My remaining questions:

1) When I have an arraylist of disposable objects, do I need to parse the
arraylist to dispose all of its items? Can myArrayList.clear do the trick?

2) Do I overload the Dispose Design Pattern dispose method correctly here:
Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean)
If Not _Disposed Then
If disposing Then
'Unmanaged resources
myMenu.Dispose()
End If

'Managed resources
myMenu = Nothing

_Disposed = True
End If
End Sub

Thanks
E.Thouin

---
Incoming mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.782 / Virus Database: 528 - Release Date: 22/10/2004



[microsoft.public.dotnet.framework]
 
R

Richard Blewett [DevelopMentor]

If Dispose is called, Finalize should never happen. Every Dispose method should have a call to GC.SuppressFinalize(this); This will prevent the finalizer running which is A Good Thing (tm). Finalizers make the GC less efficient.

Regards

Richard Blewett - DevelopMentor
http://www.dotnetconsult.co.uk/weblog
http://www.dotnetconsult.co.uk


Finalize is the last thing to happen to an object. Finalize happens after
Dispose.
 
G

Guest

Here's a sample of how I would do it. The myMenu, even if not a true object,
would have the dispose method and I would need the myMenu instance as long as
the object MenuWrapper lives.

Public Class MenuWrapper
Implements IDisposable
Private myMenu as Menu
Private disposed As Boolean = False
Public Overloads Sub Dispose()Implements IDisposable.Dispose
Dispose(true)
GC.SuppressFinalize(Me)
End Sub
Protected Overloads Overridable Sub Dispose(disposing As Boolean)
If Not (Me.disposed) Then
If (disposing) Then
' Dispose managed resources.
myMenu.Dispose()
End If

Me.disposed = true
End If
End Sub
Protected Overrides Sub Finalize()
Try
Dispose(False)
Catch

Finally
MyBase.Finalize()
End Try
End Sub
Public Sub ShowMenu()
If Me.disposed Then
Throw New ObjectDisposedException()
else
myMenu.visible = true
End if
End Sub
End Class
 
R

Richard Blewett [DevelopMentor]

Thats pretty much a perfect implementation :)

Regards

Richard Blewett - DevelopMentor
http://www.dotnetconsult.co.uk/weblog
http://www.dotnetconsult.co.uk

nntp://news.microsoft.com/microsoft.public.dotnet.framework/<[email protected]>

Here's a sample of how I would do it. The myMenu, even if not a true object,
would have the dispose method and I would need the myMenu instance as long as
the object MenuWrapper lives.

Public Class MenuWrapper
Implements IDisposable
Private myMenu as Menu
Private disposed As Boolean = False
Public Overloads Sub Dispose()Implements IDisposable.Dispose
Dispose(true)
GC.SuppressFinalize(Me)
End Sub
Protected Overloads Overridable Sub Dispose(disposing As Boolean)
If Not (Me.disposed) Then
If (disposing) Then
' Dispose managed resources.
myMenu.Dispose()
End If

Me.disposed = true
End If
End Sub
Protected Overrides Sub Finalize()
Try
Dispose(False)
Catch

Finally
MyBase.Finalize()
End Try
End Sub
Public Sub ShowMenu()
If Me.disposed Then
Throw New ObjectDisposedException()
else
myMenu.visible = true
End if
End Sub
End Class
 

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