Since all new distributions (other than large objects) always go to Gen0, GC is designed to collect data from the specified generation and below. When you call GC.Collect(2) , you tell GC to assemble from Gen0, Gen1, and Gen2.
If you are sure that you are dealing with a large number of large objects (objects that are large enough to be placed on the LOH when allocating time), the best option is to ensure that you set them to null (Nothing in VB) when you are done with them. The LOH attempt is trying to be smart and reuse blocks. For example, if you select a 1MB object on LOH and then delete it and set it to null, you will be left with a 1 MB hole. The next time you select something on an LOH of 1 MB or less, it will fill this hole (and continue to fill it until the next distribution is too large to fit in the remaining space, and at that moment it will highlight the new block.)
Keep in mind that generations in .NET are not physical things, but logical divisions that help improve GC performance. As all new distributions go to Gen0, this is always the first generation to be assembled. Each collection cycle that works, everything in the lower generation that survives in the collection, “advances” to the next higher generation (until it reaches Gen2).
In most cases, the GC does not need to go beyond collecting Gen0. The current GC implementation is able to collect Gen0 and Gen1 at the same time, but cannot collect Gen2, while Gen0 or Gen1 are assembled. (.NET 4.0 greatly facilitates this limitation and, for the most part, GC can build Gen2, while Gen0 or Gen1 can also build.)
Scott dorman
source share