views:

1049

answers:

7

I need to dispose of an object so it can release everything it owns, but it doesn't implement the IDisposable so I can't use it in a using block. How can I make the garbage collector collect it?

A: 

If the object goes out of scope and it have no external references it will be collected rather fast (likely on the next collection).

leppie
Not necessarily. E.g. if it has already move to gen 2 it could take a while and if there's a pending finalizer two collects are needed.
Brian Rasmussen
+6  A: 

You can force a collection with GC.Collect(). Be very careful using this, since a full collection can take some time. The best-practice is to just let the GC determine when the best time to collect is.

Does the object contain unmanaged resources but does not implement IDisposable? If so, it's a bug.

If it doesn't, it shouldn't matter if it gets released right away, the garbage collector should do the right thing.

Michael
I think his question is because it contains managed resources, but it uses A LOT of resources, so he want them to be released immediately when he doesn't need the object anymore.
If that is the case, let the GC just handle it. If the resource is big enough and exerting enough memory pressure, it'll be handled at the next gen 0 GC.
Michael
actually, it holds a socket and I want the socket released ASAP, but I don't have access to close the socket myself.
Malfist
@Malfist: then you need to change the object, even if that means changing vendors.
Joel Coehoorn
Can you call Socket.Close()? That will release the socket's resources.
Jon B
I got the source of the library I was using from the vendor and made the Socket public. It's all good now :)
Malfist
If by "vendor" you mean "someone I paid for this library" then the correct solution is to ditch that vendor, regardless of what you can do to the source.
Lasse V. Karlsen
+1  A: 
Joel Coehoorn
The object comes from a library, I don't have control over it. It owns a socket, and I need to close and recreate that socket but I cannot do it while it holds it and I have no access to the socket.
Malfist
Solution #1, which is your quick-fix: call GC.Collect(); Solution #2, which is the long-term (and correct) fix: Ditch that library and get a new one.
Lasse V. Karlsen
#2 is not always an option :)
alchemical
+1  A: 

I think the appropriate question is why you need to do this? What problem are you attempting to solve?

Lasse V. Karlsen
+1  A: 

You can't perform garbage collection on a single object. You could request a garbage collection by calling GC.Collect() but this will effect all objects subject to cleanup. It is also highly discouraged as it can have a negative effect on the performance of later collections.

Also, calling Dispose on an object does not clean up it's memory. It only allows the object to remove references to unmanaged resources. For example, calling Dispose on a StreamWriter closes the stream and releases the Windows file handle. The memory for the object on the managed heap does not get reclaimed until a subsequent garbage collection.

Chris Sells also discussed this on .NET Rocks. I think it was during his first appearance but the subject might have been revisited in later interviews.

http://www.dotnetrocks.com/default.aspx?showNum=10

This article by Francesco Balena is also a good reference:

When and How to Use Dispose and Finalize in C# http://www.devx.com/dotnet/Article/33167/0/page/1

Rob Windsor
A: 

Garbage collection in .NET is non deterministic, meaning you can't really control when it happens. You can suggest, but that doesn't mean it will listen.

Tells us a little bit more about the object and why you want to do this. We can make some suggestions based off of that. Code always helps. And depending on the object, there might be a Close method or something similar. Maybe the useage is to call that. If there is no Close or Dispose type of method, you probably don't want to rely on that object, as you will probably get memory leaks if in fact it does contain resourses which will need to be released.

Bob
+1  A: 

BEWARE: of f ra gm enta tion in many cases, GC.Collect() or some IDisposal is not very helpful, especially for large objects (LOH is for objects ~80kb+, performs no compaction and is subject to high levels of fragmentation for many common use cases) which will then lead to out of memory (OOM) issues even with potentially hundreds of MB free. As time marches on, things get bigger, though perhaps not this size (80 something kb) for LOH relegated objects, high degrees of parallelism exasperates this issue due simply due to more objects in less time (and likely varying in size) being instantiated/released.

Array’s are the usual suspects for this problem (it’s also often hard to identify due to non-specific exceptions and assertions from the runtime, something like “high % of large object heap fragmentation” would be swell), the prognosis for code suffering from this problem is to implement an aggressive re-use strategy.

A class in Systems.Collections.Concurrent.ObjectPool from the parallel extensions beta1 samples helps (unfortunately there is not a simple ubiquitous pattern which I have seen, like maybe some attached property/extension methods?), it is simple enough to drop in or re-implement for most projects, you assign a generator Func<> and use Get/Put helper methods to re-use your previous object’s and forgo usual garbage collection. It is usually sufficient to focus on array’s and not the individual array elements.

It would be nice if .NET 4 updated all of the .ToArray() methods everywhere to include .ToArray(T target).

Getting the hang of using SOS/windbg (.loadby sos mscoreei for CLRv4) to analyze this class of issue can help. Thinking about it, the current garbage collection system is more like garbage re-cycling (using the same physical memory again), ObjectPool is analogous to garbage re-using. If anybody remembers the 3 R’s, reducing your memory use is a good idea too, for performance sakes ;)

RandomNickName42