By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,256 Members | 1,700 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,256 IT Pros & Developers. It's quick & easy.

WeakReference not working?

P: n/a
Hi,

We have written a cache, which can have different behaviours. One of these
is a WeakReference-Cache. The purpose is that, once an object isn't referred
anymore in the application, it should dissappear from the cache.

This works almost always fine, but not for some objects, and I can't find
out why. For some reason, even when I do a "MyObject = Nothing" and a
"GC.Collect", it still has its "WeakReference.IsAlive = True"...

Anybody knows why this happens? And what can I do about it? Should I
implement IDisposable to all my objetcs? And how does that work? Do I have
to do anything special in the overriden Dispose-method?
Thanks a lot in advance,
Pieter

This is how we did the GC.Collect and the removal of the
not-anymore-used-objects...

Private Shared Sub GarbageCollect()
Dim lstID As New List(Of Integer)

GC.Collect() 'premier collect
GC.WaitForPendingFinalizers() 'attend la fin du thread
GC.Collect() 'dexičme collect pour tout enlever
GC.WaitForPendingFinalizers() 'attend la fin du thread

For Each i As Integer In dicCacheWeakReference.Keys
If Not dicCacheWeakReference(i).IsAlive Then
lstID.Add(i) 'si l'objet n'existe plus, l'ajoute dans la
liste ŕ effacer
End If
Next

For Each intID As Integer In lstID
dicCacheWeakReference.Remove(intID) 'efface les reférences morte
du cache
Next
End Sub
Jul 25 '07 #1
Share this Question
Share on Google+
12 Replies


P: n/a
Pieter wrote:
Hi,

We have written a cache, which can have different behaviours. One of these
is a WeakReference-Cache. The purpose is that, once an object isn't referred
anymore in the application, it should dissappear from the cache.

This works almost always fine, but not for some objects, and I can't find
out why. For some reason, even when I do a "MyObject = Nothing" and a
"GC.Collect", it still has its "WeakReference.IsAlive = True"...

Anybody knows why this happens?
A garbage collection isn't guaranteed to collect _all_ objects that are
collectable, it only collects the objects that are efficient to collect.

A garbage collection usually only collects objects in the first
generation heap. As the objects that you cache probably lives for a
longer time than most objects, they are likely to have been moved to the
second or third generation heap.
And what can I do about it? Should I
implement IDisposable to all my objetcs? And how does that work? Do I have
to do anything special in the overriden Dispose-method?
Why is there any reason to do anything about it? If the garbage
collector doesn't collect the objects, the memory that they are using
isn't needed. If the application runs out of memory in the current heap,
the garbage collector does a more thorough collection to collect
anything that is possible, before more memory is requested from the system.
>
Thanks a lot in advance,
Pieter

This is how we did the GC.Collect and the removal of the
not-anymore-used-objects...

Private Shared Sub GarbageCollect()
Dim lstID As New List(Of Integer)

GC.Collect() 'premier collect
GC.WaitForPendingFinalizers() 'attend la fin du thread
GC.Collect() 'dexičme collect pour tout enlever
GC.WaitForPendingFinalizers() 'attend la fin du thread

For Each i As Integer In dicCacheWeakReference.Keys
If Not dicCacheWeakReference(i).IsAlive Then
lstID.Add(i) 'si l'objet n'existe plus, l'ajoute dans la
liste ŕ effacer
End If
Next

For Each intID As Integer In lstID
dicCacheWeakReference.Remove(intID) 'efface les reférences morte
du cache
Next
End Sub
Why are you calling GC.Collect at all? The memory management handles
itself, and there is hardly ever any reason to interfer with it.

Unless you know something important about the memory usage that the
garbage collector don't, you will likely reduce the performance of the
application rather than improve it.

--
Göran Andersson
_____
http://www.guffa.com
Jul 25 '07 #2

P: n/a
"Göran Andersson" <gu***@guffa.comwrote in message
news:u$**************@TK2MSFTNGP02.phx.gbl...
>
Why is there any reason to do anything about it?
The whole purpose is not collecting memory, but throwing away the object...

This is what is needed: If the user wants to open object A, but object A is
already opened (and used), it should return the same objet. But if it's not
opened (or opened before but not used anymore), it should return a fresh
copy of the database.

That's exactly why we are using WeakReferences...

If the application runs out of memory in the current heap, the garbage
collector does a more thorough collection to collect anything that is
possible, before more memory is requested from the system.
And can I force him to do this more thorough collection?
And better (because I don't really like using the garbage collector): isn't
there another way to achieve this behaviour?

Thanks,

Pieter
Jul 25 '07 #3

P: n/a

"Pieter" <pi****************@hotmail.comwrote in message
news:%2****************@TK2MSFTNGP04.phx.gbl...
"Göran Andersson" <gu***@guffa.comwrote in message
news:u$**************@TK2MSFTNGP02.phx.gbl...
>>
Why is there any reason to do anything about it?

The whole purpose is not collecting memory, but throwing away the
object...

This is what is needed: If the user wants to open object A, but object A
is already opened (and used), it should return the same objet. But if it's
not opened (or opened before but not used anymore), it should return a
fresh copy of the database.

That's exactly why we are using WeakReferences...
And that's how it will work. But you can't force the GC to free your
instance. It will do if it deems it necessary. Just don't worry about it.
>If the application runs out of memory in the current heap, the garbage
collector does a more thorough collection to collect anything that is
possible, before more memory is requested from the system.

And can I force him to do this more thorough collection?
You can, but you shouldn't. Call
GC.Collect(2);
GC.WaitForPendingFinalizers();
GC.Collect(2);

But don't do it. In most cases, this will make things worse.
And better (because I don't really like using the garbage collector):
isn't there another way to achieve this behaviour?
No... that's (thankfully) .NET.

Kind regars,
Henning Krause

Jul 25 '07 #4

P: n/a
Hi Pieter,

The normal purpose for creating weakly referenced objects is to
allow them to remain in memory as long as memory permits.
If there is memory pressure the garbage collector will run and
wr objects may be collected. This way if memory is abundant
your wr cache objects will be in memory, if not, they will be
collected (forcing you to re-load them the next time they are
needed).

You can simulate this situation by running GC.Collect() and
then WaitForPendingFinalizers(). If you are using wr correctly
they will be be removed from memory after GC.Collect.

Please note that I am *not* saying that you run the garbage
collector manually when using wr. The above is for testing/debugging
purposes only to help simulate the situation where wr objects
are removed from memory.

One mistake people make is creating a regular (non-weak)
object reference to an object that is the target of a wr. In
this case the object will *survive* garbage collections which is
not the behavior you wanted when you decided on using weak
references.

You can use CLR Profiler (free) or .NET Memory Profiler ($)
to help you track down the reference that is causing the wr
to not be collected.

John

"Pieter" <pi****************@hotmail.comwrote in message
news:e6**************@TK2MSFTNGP04.phx.gbl...
Hi,

We have written a cache, which can have different behaviours. One of these
is a WeakReference-Cache. The purpose is that, once an object isn't
referred anymore in the application, it should dissappear from the cache.

This works almost always fine, but not for some objects, and I can't find
out why. For some reason, even when I do a "MyObject = Nothing" and a
"GC.Collect", it still has its "WeakReference.IsAlive = True"...

Anybody knows why this happens? And what can I do about it? Should I
implement IDisposable to all my objetcs? And how does that work? Do I have
to do anything special in the overriden Dispose-method?
Thanks a lot in advance,
Pieter

This is how we did the GC.Collect and the removal of the
not-anymore-used-objects...

Private Shared Sub GarbageCollect()
Dim lstID As New List(Of Integer)

GC.Collect() 'premier collect
GC.WaitForPendingFinalizers() 'attend la fin du thread
GC.Collect() 'dexičme collect pour tout enlever
GC.WaitForPendingFinalizers() 'attend la fin du thread

For Each i As Integer In dicCacheWeakReference.Keys
If Not dicCacheWeakReference(i).IsAlive Then
lstID.Add(i) 'si l'objet n'existe plus, l'ajoute dans la
liste ŕ effacer
End If
Next

For Each intID As Integer In lstID
dicCacheWeakReference.Remove(intID) 'efface les reférences
morte du cache
Next
End Sub


Jul 25 '07 #5

P: n/a
The fact that a weak reference is still alive after *multiple*
full garbage collections is an indication that there is regular
object reference pointing to the object. This is a memory
leak and should be corrected.

I agree with you that in most cases GC.Collect should
not be used except for debugging. However, if an object (that
should be collectable) survives multiple full collections then it is
in fact not collectable and is evidence of a memory leak.

John

"Göran Andersson" <gu***@guffa.comwrote in message
news:u$**************@TK2MSFTNGP02.phx.gbl...
Pieter wrote:
>Hi,

We have written a cache, which can have different behaviours. One of
these is a WeakReference-Cache. The purpose is that, once an object isn't
referred anymore in the application, it should dissappear from the cache.

This works almost always fine, but not for some objects, and I can't find
out why. For some reason, even when I do a "MyObject = Nothing" and a
"GC.Collect", it still has its "WeakReference.IsAlive = True"...

Anybody knows why this happens?

A garbage collection isn't guaranteed to collect _all_ objects that are
collectable, it only collects the objects that are efficient to collect.

A garbage collection usually only collects objects in the first generation
heap. As the objects that you cache probably lives for a longer time than
most objects, they are likely to have been moved to the second or third
generation heap.
>And what can I do about it? Should I implement IDisposable to all my
objetcs? And how does that work? Do I have to do anything special in the
overriden Dispose-method?

Why is there any reason to do anything about it? If the garbage collector
doesn't collect the objects, the memory that they are using isn't needed.
If the application runs out of memory in the current heap, the garbage
collector does a more thorough collection to collect anything that is
possible, before more memory is requested from the system.
>>
Thanks a lot in advance,
Pieter

This is how we did the GC.Collect and the removal of the
not-anymore-used-objects...

Private Shared Sub GarbageCollect()
Dim lstID As New List(Of Integer)

GC.Collect() 'premier collect
GC.WaitForPendingFinalizers() 'attend la fin du thread
GC.Collect() 'dexičme collect pour tout enlever
GC.WaitForPendingFinalizers() 'attend la fin du thread

For Each i As Integer In dicCacheWeakReference.Keys
If Not dicCacheWeakReference(i).IsAlive Then
lstID.Add(i) 'si l'objet n'existe plus, l'ajoute dans la
liste ŕ effacer
End If
Next

For Each intID As Integer In lstID
dicCacheWeakReference.Remove(intID) 'efface les reférences
morte du cache
Next
End Sub

Why are you calling GC.Collect at all? The memory management handles
itself, and there is hardly ever any reason to interfer with it.

Unless you know something important about the memory usage that the
garbage collector don't, you will likely reduce the performance of the
application rather than improve it.

--
Göran Andersson
_____
http://www.guffa.com

Jul 25 '07 #6

P: n/a
If done properly a weak reference will be collected
during a full garbage collection (GC.Collect()). The
fact that it is not collected shows that Pieter has a memory
leak that needs to be corrected.

John

"Henning Krause [MVP - Exchange]" <ne***************@this.infinitec.de>
wrote in message news:e$**************@TK2MSFTNGP03.phx.gbl...
>
"Pieter" <pi****************@hotmail.comwrote in message
news:%2****************@TK2MSFTNGP04.phx.gbl...
>"Göran Andersson" <gu***@guffa.comwrote in message
news:u$**************@TK2MSFTNGP02.phx.gbl...
>>>
Why is there any reason to do anything about it?

The whole purpose is not collecting memory, but throwing away the
object...

This is what is needed: If the user wants to open object A, but object A
is already opened (and used), it should return the same objet. But if
it's not opened (or opened before but not used anymore), it should return
a fresh copy of the database.

That's exactly why we are using WeakReferences...

And that's how it will work. But you can't force the GC to free your
instance. It will do if it deems it necessary. Just don't worry about it.
>>If the application runs out of memory in the current heap, the garbage
collector does a more thorough collection to collect anything that is
possible, before more memory is requested from the system.

And can I force him to do this more thorough collection?
You can, but you shouldn't. Call
GC.Collect(2);
GC.WaitForPendingFinalizers();
GC.Collect(2);

But don't do it. In most cases, this will make things worse.
>And better (because I don't really like using the garbage collector):
isn't there another way to achieve this behaviour?

No... that's (thankfully) .NET.

Kind regars,
Henning Krause

Jul 25 '07 #7

P: n/a
Hi John,
You are right.

There is a pretty cool memory analzyer from SciTech. They also have a 30
days trial version.

Kind regards,
Henning Krause
"John" <jo**@donotspam.invalidwrote in message
news:eO**************@TK2MSFTNGP03.phx.gbl...
If done properly a weak reference will be collected
during a full garbage collection (GC.Collect()). The
fact that it is not collected shows that Pieter has a memory
leak that needs to be corrected.

John

"Henning Krause [MVP - Exchange]" <ne***************@this.infinitec.de>
wrote in message news:e$**************@TK2MSFTNGP03.phx.gbl...
>>
"Pieter" <pi****************@hotmail.comwrote in message
news:%2****************@TK2MSFTNGP04.phx.gbl...
>>"Göran Andersson" <gu***@guffa.comwrote in message
news:u$**************@TK2MSFTNGP02.phx.gbl...

Why is there any reason to do anything about it?

The whole purpose is not collecting memory, but throwing away the
object...

This is what is needed: If the user wants to open object A, but object A
is already opened (and used), it should return the same objet. But if
it's not opened (or opened before but not used anymore), it should
return a fresh copy of the database.

That's exactly why we are using WeakReferences...

And that's how it will work. But you can't force the GC to free your
instance. It will do if it deems it necessary. Just don't worry about it.
>>>If the application runs out of memory in the current heap, the garbage
collector does a more thorough collection to collect anything that is
possible, before more memory is requested from the system.

And can I force him to do this more thorough collection?
You can, but you shouldn't. Call
GC.Collect(2);
GC.WaitForPendingFinalizers();
GC.Collect(2);

But don't do it. In most cases, this will make things worse.
>>And better (because I don't really like using the garbage collector):
isn't there another way to achieve this behaviour?

No... that's (thankfully) .NET.

Kind regars,
Henning Krause

Jul 25 '07 #8

P: n/a
Pieter wrote:
"Göran Andersson" <gu***@guffa.comwrote in message
news:u$**************@TK2MSFTNGP02.phx.gbl...
>Why is there any reason to do anything about it?

The whole purpose is not collecting memory, but throwing away the object...

This is what is needed: If the user wants to open object A, but object A is
already opened (and used), it should return the same objet. But if it's not
opened (or opened before but not used anymore), it should return a fresh
copy of the database.

That's exactly why we are using WeakReferences...
A WeakReference doesn't work that way. The memory management in .NET
doesn't use reference counting, so there is no way that a WeakReference
can know when there are no more references to the object.

The way to control the life cycle of an object in .NET is to use the
IDisposable interface.

What you need to do is use reference counting in your cache, and
implement the IDisposable interface in the object. When the object is
disposed, it should inform the cache so that it can decrement the
reference count, so that the object can be removed from the cache when
the reference count reaches zero.
>If the application runs out of memory in the current heap, the garbage
collector does a more thorough collection to collect anything that is
possible, before more memory is requested from the system.

And can I force him to do this more thorough collection?
Yes, but you shouldn't.
And better (because I don't really like using the garbage collector): isn't
there another way to achieve this behaviour?
Exactly. You are trying to use the garbage collector for something that
it can't do, so you should implement it in a way that works instead. :)

--
Göran Andersson
_____
http://www.guffa.com
Jul 25 '07 #9

P: n/a
Hello,
A WeakReference doesn't work that way. The memory management in .NET
doesn't use reference counting, so there is no way that a WeakReference
can know when there are no more references to the object.
Yes it does work this way. A WeakReference does not have a strong reference
to the object but holds the GCHandle of the item.
>
The way to control the life cycle of an object in .NET is to use the
IDisposable interface.
Nope. IDisposable is used to release unamanged resources. Not managed ones.
>
What you need to do is use reference counting in your cache, and implement
the IDisposable interface in the object. When the object is disposed, it
should inform the cache so that it can decrement the reference count, so
that the object can be removed from the cache when the reference count
reaches zero.
The whole GC is about not having to worry about reference counting. Why do
you want to bring it back?

A WeakReference will work fine in a cache. The GC will release it if there
is no other strong reference.

Kind regards,
Henning Krause

Jul 26 '07 #10

P: n/a
"John" <jo**@donotspam.invalidwrote in message
news:uj**************@TK2MSFTNGP02.phx.gbl...
You can use CLR Profiler (free) or .NET Memory Profiler ($)
to help you track down the reference that is causing the wr
to not be collected.
Ouwch, I got very nice and colourfull schema's with the CLR Profiler, but in
which screen exactly can I track down my problem? hihi :-)
Jul 26 '07 #11

P: n/a
Henning Krause [MVP - Exchange] wrote:
>A WeakReference doesn't work that way. The memory management in .NET
doesn't use reference counting, so there is no way that a
WeakReference can know when there are no more references to the object.

Yes it does work this way. A WeakReference does not have a strong
reference to the object but holds the GCHandle of the item.
That's not what we are talking about. What Peter wants is to know if the
object is used, not if it has been collected. A weak reference can not
be used for that, because it doesn't work that way.
>The way to control the life cycle of an object in .NET is to use the
IDisposable interface.

Nope. IDisposable is used to release unamanged resources. Not managed ones.
As there are no destructors in .NET, the IDisposable interface is used
when you need to control the life cycle of objects. It's ususally used
because the object has unmanaged resourctes that needs to be released,
but there is nothing that requires the object to have unmanaged resources.
>What you need to do is use reference counting in your cache, and
implement the IDisposable interface in the object. When the object is
disposed, it should inform the cache so that it can decrement the
reference count, so that the object can be removed from the cache when
the reference count reaches zero.

The whole GC is about not having to worry about reference counting. Why
do you want to bring it back?
Because Peter needs to know if the object is used or not, and as there
can be more than one reference to the object, the references needs to be
counted.
A WeakReference will work fine in a cache. The GC will release it if
there is no other strong reference.
Yes, but that is not what Peter wants. Or in his own words:

"The whole purpose is not collecting memory, but throwing away the object"

--
Göran Andersson
_____
http://www.guffa.com
Jul 26 '07 #12

P: n/a
I'm not finding a way via those Profilers to see what's putting a reference
to my object :-S Anybody has another idea? Or can someone point me out how I
should be able to see it?

Thanks a lot,
Pieter
Jul 27 '07 #13

This discussion thread is closed

Replies have been disabled for this discussion.