>> You example doesn't help because there's nothing in Foo that needs
>> disposing, and Dispose isn't related to GC as you seem to be assuming.
[quoted text clipped - 8 lines]
> occupies grows more. I wait and nothing happens. Shouldn't GC release
> the memory as long as an object is not referenced any more?
I think to some degree it's a waste of time trying to help GC do its job
better in the way it seems you're thinking, as it is a fairly indeterminate
mechanism in the first place. It is somewhat important in some cases to
help GC have less to do though, because it can become a performance issue.
For example, using lots of stringbuilders for what are really just simple
concatenations. But that really manifests itself as a performance issue
more than a memory one in my testing.
As somebody else said, the Dispose pattern is for making sure UNMANAGED
resources inside your classes get cleaned up. That is, making sure there
are no memory leaks in things that GC doesn't try to deal with. That's why
the statement "Dispose doesn't have anything to do with GC".
I have no idea what "several times more memory than equivalent native
applications" means. Equivalent how -Functionality? Code? That's such a
nebulous comparison I don't think I'd spend much time worrying about that
either.
Is there a specific problem you're having or specific reason you think you
may have a memory leak in the application?
Petros Amiridis - 21 Jun 2006 14:22 GMT
> As somebody else said, the Dispose pattern is for making sure
> UNMANAGED resources inside your classes get cleaned up.
This more clear to me now. I really thought Dispose would help GC.
Thank you and the rest for the clarification.
> I have no idea what "several times more memory than equivalent native
> applications" means. Equivalent how -Functionality? Code? That's
> such a nebulous comparison I don't think I'd spend much time worrying
> about that either.
I admit that is based entirely on my experience and not in crystal
clear measurements. My heuristics mechanism takes under consideration
all the factors: Functionality, Number of Forms etc. Sure, I might be
inaccurate in my comparison, but the numbers are very different between
native and managed applications. My native applications take memory and
give it back as soon as I don't need the resources I've used. In
managed applications, the memory keeps being eaten until the GC decides
it is time to collect. The problem with this is that my customer does
run more applications than one. The customer also uses his computer for
other puproses, so she runs third party applications too. So to
conclude, I don't have a specific problem, other than the need to tell
my customers to add some more memory to their machines. Maybe it is not
a leak, it is just taking the GC a long time to collect back the memory.

Signature
Petros
Simon Hart - 21 Jun 2006 16:36 GMT
>> As somebody else said, the Dispose pattern is for making sure
>> UNMANAGED resources inside your classes get cleaned up.
[quoted text clipped - 20 lines]
> my customers to add some more memory to their machines. Maybe it is not
> a leak, it is just taking the GC a long time to collect back the memory.
The GC will kick in when required - for example memory is low, but it will
only release managed
objects if: A. They have been marked to be Diposed or B. They are
unreachable on the heap.
Regards
Simon.
Göran Andersson - 21 Jun 2006 23:19 GMT
>>> As somebody else said, the Dispose pattern is for making sure
>>> UNMANAGED resources inside your classes get cleaned up.
[quoted text clipped - 26 lines]
> Regards
> Simon.
Actually only condition B is relevant.
You can't mark objects to be collected, the only way to make them
collectable is to make them unreachable.
Carl Daniel [VC++ MVP] - 21 Jun 2006 14:49 GMT
> As somebody else said, the Dispose pattern is for making sure
> UNMANAGED resources inside your classes get cleaned up.
I would take exception with that statement. Dispose is for making sure
resources that are not simply managed heap allocations get cleaned up.
Unmanaged resources such as handles or Win32 memory allocations are fine
examples of such, but there are certainly managed examples as well. A
common example of a managed resource that needs to be explicitly cleaned up
is a callback (delegate) which can keep an object alive long after you're
done with it, consuming both memory and CPU resources making callbacks to an
object that no one cares about anymore.
-cd
Simon Hart - 21 Jun 2006 16:34 GMT
Agree. We often use the Dispose (IDisposable) for cleaning managed resources
as well as unmanaged. We tend to use the Finalizer (Destructor) for
unmanaged deallocation.
Regards
Simon.
>> As somebody else said, the Dispose pattern is for making sure
>> UNMANAGED resources inside your classes get cleaned up.
[quoted text clipped - 9 lines]
>
> -cd
Markus Stoeger - 21 Jun 2006 19:48 GMT
> Agree. We often use the Dispose (IDisposable) for cleaning managed resources
> as well as unmanaged. We tend to use the Finalizer (Destructor) for
> unmanaged deallocation.
Could you explain why you prefer the finalizer instead of a manual call
to Dispose for freeing unmanaged resources?
As far as I know you can never tell when the GC will finalize an object.
So it might keep floating around forever as well. Which means that you
could run out of handles for example.
Maybe I've misunderstood something behind GC and the finalizer?.
Max
Göran Andersson - 21 Jun 2006 23:23 GMT
>> Agree. We often use the Dispose (IDisposable) for cleaning managed
>> resources as well as unmanaged. We tend to use the Finalizer
[quoted text clipped - 10 lines]
>
> Max
No, that is correct.
The Dispose method should be used to free resources. The finalizer
should call Dispose as a backup if the program failed to call it.
Carl Daniel [VC++ MVP] - 22 Jun 2006 00:12 GMT
>>> Agree. We often use the Dispose (IDisposable) for cleaning managed
>>> resources as well as unmanaged. We tend to use the Finalizer
[quoted text clipped - 15 lines]
> The Dispose method should be used to free resources. The finalizer should
> call Dispose as a backup if the program failed to call it.
More specifically, the recommended structure for Finalize and Dispose is:
class C : IDisposable
{
void IDisposable.Dispose()
{
Dispose(true);
}
~C()
{
Dispose(false)
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// free managed resources here
GC.SuppressFinalize(this);
}
// free unmanaged resources here
}
}
The C++/CLI compiler automatically implements this structure, while in C#/VB
you have to do it yourself. Current versions of FxCop will raise warnings
if your class implements IDisposable but doesn't do it this way.
Of course, if your class cannot be derived from, then there's no need for
Dispose(bool) to be virtual.
-cd
-cd
Michael D. Ober - 22 Jun 2006 12:51 GMT
I don't know about the C# environment, but VB 2005 can be configured to
insert the dispose pattern, as well as other implementation patterns, when
you add the Implements clause to the class definition and press return.
Mike Ober.
> >>> Agree. We often use the Dispose (IDisposable) for cleaning managed
> >>> resources as well as unmanaged. We tend to use the Finalizer
[quoted text clipped - 53 lines]
>
> -cd
Daniel Billingsley - 22 Jun 2006 12:31 GMT
Let's talk. :)
This would apply to simple events then, since they are really just fancy
delegates. I've never heard of anybody talk of implementing Dispose in a
class just because it raises events. Should we?
Let's lay some groundwork. The problem with keeping an object "alive" is
because something references it, not the other way around. Let's imagine an
ObjectB that has a reference to ObjectA because ObjectA was previously
hooked to an event in ObjectB (creating a delegate reference as you
describe).
Now ObjectB goes out of scope. It obviously isn't "making callbacks" any
more, so there's no reason for it to have Dispose() for that reason. The
problem with keeping ObjectA "alive" consuming memory is only temporary
until GC does its thing with ObjectB. That's the whole point of GC.
But, for you GC gurus - isn't GC smart enough to know that the only
reference to ObjectA is from a "dead" ObjectB and therefore consider ObjectA
itself eligible for collection?
>> As somebody else said, the Dispose pattern is for making sure
>> UNMANAGED resources inside your classes get cleaned up.
[quoted text clipped - 9 lines]
>
> -cd
Michael D. Ober - 22 Jun 2006 12:52 GMT
> Let's talk. :)
>
[quoted text clipped - 16 lines]
> reference to ObjectA is from a "dead" ObjectB and therefore consider ObjectA
> itself eligible for collection?
Yes it is. I have explicitely tested this scenerio.
Mike.
> >> As somebody else said, the Dispose pattern is for making sure
> >> UNMANAGED resources inside your classes get cleaned up.
[quoted text clipped - 9 lines]
> >
> > -cd
Göran Andersson - 22 Jun 2006 13:07 GMT
Yes, it is.
When the GC does it's thing, it starts out by considering all objects as
collectable, then looks for references to find out which objects are not
collectable. As it doesn't look in collectable objects for references,
it still sees that unreachable objects are collectable although they
reference each other.
"Every object charged with being collectable will be presumed guilty
until proved reachable." ;)
> Let's talk. :)
>
[quoted text clipped - 29 lines]
>>
>> -cd