When I perform a AppDomain.Unload(myDomain) I expect it to also do a full garbage collection.
According to Jeffrey Richter in \"CLR via C#\" he says that during an A
Additional Notes:
After some mail exchange with Jeffrey Richter who was kind enough to have a look at the question:
OK, I read your post.
First, the array will not be GC’d until the XMLClass object is GC’d and it takes TWO GCs to collect this object because it contains a Finalize method.
Second, unloading an appdomain at least performs the marking phase of the GC since this is the only way to determine which objects are unreachable so that their Finalize methods can be called.
However, the compact part of the GC might or might not be done when unloading a GC. Calling GC.CollectionCount obvious does not tell the whole story. It is not showing that the GC marking phase did occur.
And, it’s possible that AppDomain.Unload starts a GC via some internal code which does not cause the collection count variables to be incremented. We already know for a fact that the marking phase is being performed and that collection count is not reflecting this.A better test would be to look at some object addresses in the debugger and see if compaction actually occurs. If it does (and I suspect it does), then the collection count is just not being updated correctly.
If you want to post this to the web site as my response, you can.
After taking his advice and looking into SOS (also removed the finalizer) it revealed this:
Before AppDomain.Unload:
!EEHeap -gc
Number of GC Heaps: 1
generation 0 starts at 0x0180b1f0
generation 1 starts at 0x017d100c
generation 2 starts at 0x017d1000
ephemeral segment allocation context: none
segment begin allocated size
017d0000 017d1000 01811ff4 0x00040ff4(266228)
Large object heap starts at 0x027d1000
segment begin allocated size
027d0000 027d1000 02f75470 0x007a4470(8012912)
Total Size 0x7e5464(8279140)
------------------------------
GC Heap Size 0x7e5464(8279140)
After AppDomain.Unload (same addresses, no heap compaction was done)
!EEHeap -gc
Number of GC Heaps: 1
generation 0 starts at 0x0180b1f0
generation 1 starts at 0x017d100c
generation 2 starts at 0x017d1000
ephemeral segment allocation context: none
segment begin allocated size
017d0000 017d1000 01811ff4 0x00040ff4(266228)
Large object heap starts at 0x027d1000
segment begin allocated size
027d0000 027d1000 02f75470 0x007a4470(8012912)
Total Size 0x7e5464(8279140)
------------------------------
GC Heap Size 0x7e5464(8279140)
After GC.Collect(), addresses differ indicating heap compaction was done.
!EEHeap -gc
Number of GC Heaps: 1
generation 0 starts at 0x01811234
generation 1 starts at 0x0180b1f0
generation 2 starts at 0x017d1000
ephemeral segment allocation context: none
segment begin allocated size
017d0000 017d1000 01811ff4 0x00040ff4(266228)
Large object heap starts at 0x027d1000
segment begin allocated size
027d0000 027d1000 027d3240 0x00002240(8768)
Total Size 0x43234(274996)
------------------------------
GC Heap Size 0x43234(274996)
After more sos the conclusion I've reached is that it is surely by design, and that heap compaction is not necessarily done. The only thing you can really be sure during an AppDomain unload is that objects will get to be marked as unreachable and will be collected during the next garbage collection (which like I said, it's not done exactly when you unload your application domain, unless there's a coincidence).
EDIT: I've also asked Maoni Stephens, who works directly in the GC team. You can read her response somewhere in the comments here. She confirms that it is by design. Case closed :)
Probably by design, but I don't understand why you want this behaviour (explicit GC.Collect). As long as the finalizers are called, the objects are removed from the finalizer queue and are ready to be garbage collected if required (the gc thread will kick in when necessary).
You can probably use some nasty unmanaged allocation and some heavy interop, or code it in unmanaged c++ and then use a managed wrapper to access it through C#, but as long as you stay within the managed .Net world, no.
It is more wise to take a second look at your architecture instead of focusing on trying to play the role of the garbage collector.