<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><title type="html">Chris Lyon's WebLog</title><subtitle type="html">Or How I Learned To Stop Worrying And Love The GC</subtitle><id>http://blogs.msdn.com/b/clyon/atom.aspx</id><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/clyon/" /><link rel="self" type="application/atom+xml" href="http://blogs.msdn.com/b/clyon/atom.aspx" /><generator uri="http://telligent.com" version="5.6.50428.7875">Telligent Evolution Platform Developer Build (Build: 5.6.50428.7875)</generator><updated>2005-03-18T13:43:00Z</updated><entry><title>The GC Test Team is Hiring!</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/clyon/archive/2007/03/23/the-gc-test-team-is-hiring.aspx" /><id>http://blogs.msdn.com/b/clyon/archive/2007/03/23/the-gc-test-team-is-hiring.aspx</id><published>2007-03-23T22:42:00Z</published><updated>2007-03-23T22:42:00Z</updated><content type="html">&lt;P&gt;Tired of the same old “garbage”? Do you want to be the tester for one of the most challenging technical areas of the Common Language Runtime (CLR) and work with the industry’s top developers, architects, and distinguished engineers? The CLR team is looking for a highly motivated and outstanding technical person to test the world class CLR Garbage Collector and help make it better. If you are interested in figuring out new ways to drive how the CLR GC operates under complex technical scenarios, such as in Exchange Server, SQL Server, ASP.NET, and WPF (Windows Presentation Framework), come work for the CLR GC team!&amp;nbsp;&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;Edit: Updated link&lt;/P&gt;
&lt;P&gt;Edit: Position has been filled.&amp;nbsp; Thanks!&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1939555" width="1" height="1"&gt;</content><author><name>clyon</name><uri>http://blogs.msdn.com/clyon/ProfileUrlRedirect.ashx</uri></author><category term="Misc" scheme="http://blogs.msdn.com/b/clyon/archive/tags/Misc/" /></entry><entry><title>New In Orcas Part 3: GC Latency Modes</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/clyon/archive/2007/03/12/new-in-orcas-part-3-gc-latency-modes.aspx" /><id>http://blogs.msdn.com/b/clyon/archive/2007/03/12/new-in-orcas-part-3-gc-latency-modes.aspx</id><published>2007-03-12T22:10:00Z</published><updated>2007-03-12T22:10:00Z</updated><content type="html">&lt;P&gt;As you may know, there are different GC modes to choose from depending on the type of application you’re using:&amp;nbsp; Server GC, Workstation GC, and Concurrent GC (&lt;A class="" href="http://blogs.msdn.com/clyon/archive/2004/09/08/226981.aspx" mce_href="http://blogs.msdn.com/clyon/archive/2004/09/08/226981.aspx"&gt;more info&lt;/A&gt;).&amp;nbsp; These settings are process-wide, set at the beginning of the process.&amp;nbsp; Once the GC mode is set, it cannot be changed.&amp;nbsp; &lt;BR&gt;In Orcas, we’ve added the concept of GC Latency Modes that while process-wide, can be changed during the lifetime of the process to meet an application’s needs.&lt;BR&gt;The Latency Modes can be accessed as new properties onto the GCSettings class:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;CODE&gt;System.Runtime.GCLatencyMode System.Runtime.GCSettings.LatencyMode { get; set; } &lt;/CODE&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;The values for GCLatencyMode are Batch, Interactive and LowLatency.&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Batch:&amp;nbsp; This mode is designed for maximum throughput, at the expense of responsiveness.&amp;nbsp;&amp;nbsp; It is best for applications with no UI or server-side operations and is equivalent to Workstation GC without Concurrent GC.&amp;nbsp;&amp;nbsp; If Concurrent GC is enabled, switching to Batch mode will prevent any further concurrent collections.&amp;nbsp; This is the only valid mode for Server GC.&lt;/LI&gt;
&lt;LI&gt;Interactive:&amp;nbsp; This mode balances responsiveness with throughput.&amp;nbsp; It is designed for applications with UI and is the default Latency Mode, equivalent to Workstation GC with Concurrent GC.&amp;nbsp;&amp;nbsp; This mode is not available on Server GC.&amp;nbsp;&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;LowLatency:&amp;nbsp; This mode is meant for short-term, time-sensitive operations where interruptions from the GC may be disruptive, like animation rendering or data acquisition functions.&amp;nbsp; This mode is not available on Server GC.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;How does LowLatency mode work?&lt;/P&gt;
&lt;P&gt;When you set the latency mode to LowLatency, the GC will perform almost no generation 2 collections, nor will it start any new concurrent collections.&amp;nbsp; Since generation 2 is unbounded and can become very large, collecting it can cause your managed threads to pause for short amounts of time.&amp;nbsp; This can be unacceptable for certain scenarios.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;&lt;EM&gt;To be clear, I’m not talking about real-time application requirements, rather requirements that a short-running block of code run smoothly with minimal interruptions from the runtime.&amp;nbsp; LowLatency mode is not real-time mode.&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;I mentioned above that in LowLatency mode, the GC will perform almost no most generation 2 collections, but there are situations when it will.&amp;nbsp; As we know, there are three things that cause the GC to perform a collection (&lt;A class="" href="http://blogs.msdn.com/maoni/archive/2004/06/15/156626.aspx" mce_href="http://blogs.msdn.com/maoni/archive/2004/06/15/156626.aspx"&gt;more info&lt;/A&gt;):&lt;BR&gt;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Allocation exceeds the Gen0 threshold – normally, these collections can escalate into full heap collections.&amp;nbsp; With LowLatency, generation 1 is the maximum generation that will be collected, possibly promoting objects to generation 2.&lt;/LI&gt;
&lt;LI&gt;System.GC.Collect is called – this will continue to work as expected.&amp;nbsp; If you specify to collect generation 2, the GC will honor your request regardless of the Latency Mode.&lt;/LI&gt;
&lt;LI&gt;System is in low memory situation – the OS has raised an event telling the runtime that it is low on system memory.&amp;nbsp; In this ase the GC will perform a generation 2 collection to attempt to free memory.&amp;nbsp; The alternative is to allow the OS to begin paging which will generally have worse pause times than a full collection.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;How to safely use LowLatency mode&lt;/P&gt;
&lt;P&gt;As you might have guessed, since generation 2 is rarely collected, OutOfMemoryExceptions are more likely under LowLatency mode.&amp;nbsp; Here are some guidelines to follow to avoid potential problems:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Keep the amount of time spent in LowLatency as short as possible.&amp;nbsp; Remember, you’re changing the behavior of the GC, which can lead to sub-optimal performance in the long-run.&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;While in LowLatency mode, minimize the number of allocations you make, in particular allocations onto the Large Object Heap and pinned objects.&lt;/LI&gt;
&lt;LI&gt;Be mindful of other threads that could be allocating.&amp;nbsp; Remember, these settings are process-wide, so you could generate an OutOfMemoryException on any thread that may be allocating.&lt;/LI&gt;
&lt;LI&gt;Wrap the LowLatency code in a CER (&lt;A class="" href="http://blogs.msdn.com/bclteam/archive/2005/06/14/429181.aspx" mce_href="http://blogs.msdn.com/bclteam/archive/2005/06/14/429181.aspx"&gt;more info&lt;/A&gt;).&lt;/LI&gt;
&lt;LI&gt;Remember to set the latency mode back to avoid hard-to debug OutOfMemoryExceptions later.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Here’s a code sample of how to use LowLatency mode&lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;CODE&gt;
&lt;P&gt;// preallocate objects here&lt;BR&gt;GCLatencyMode oldMode = GCSettings.LatencyMode;&lt;BR&gt;RuntimeHelpers.PrepareConstrainedRegions();&lt;BR&gt;try&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; GCSettings.LatencyMode = GCLatencyMode.LowLatency;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // perform time-sensitive actions here&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; minimize:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; -all allocations, especially LOH allocations&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; -pinning&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; -allocations on other threads&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;BR&gt;}&lt;BR&gt;catch (ApplicationException)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // catch any exceptions you expect your application to throw&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // perform cleanup code&lt;BR&gt;}&lt;BR&gt;finally&lt;BR&gt;{&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // always set the mode back!&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; GCSettings.LatencyMode = oldMode; &lt;BR&gt;}&lt;/P&gt;&lt;/CODE&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Remember, this mode can cause failures in your application, so please use good judgment when using it.&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1867061" width="1" height="1"&gt;</content><author><name>clyon</name><uri>http://blogs.msdn.com/clyon/ProfileUrlRedirect.ashx</uri></author><category term="GC" scheme="http://blogs.msdn.com/b/clyon/archive/tags/GC/" /><category term="Orcas" scheme="http://blogs.msdn.com/b/clyon/archive/tags/Orcas/" /></entry><entry><title>New In Orcas Part 2: GC Collection Modes</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/clyon/archive/2007/03/07/new-in-orcas-part-2-gc-collection-modes.aspx" /><id>http://blogs.msdn.com/b/clyon/archive/2007/03/07/new-in-orcas-part-2-gc-collection-modes.aspx</id><published>2007-03-08T01:14:00Z</published><updated>2007-03-08T01:14:00Z</updated><content type="html">&lt;P&gt;In Orcas we’ve added an overload to System.GC.Collect():&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;CODE&gt;void System.GC.Collect(int generation, System.GCCollectionMode mode)&lt;/CODE&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Where generation is the highest generation to collect (from 0 to System.GC.MaxGeneration) and mode can be:&lt;BR&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Default:&amp;nbsp; the same behavior if you called GC.Collect without specifying the mode.&amp;nbsp; Currently this is the same behavior as Forced, but this is subject to change in future versions of the runtime.&lt;/LI&gt;
&lt;LI&gt;Forced:&amp;nbsp; guarantees a collection occurs for all the generations up to and including generation.&amp;nbsp; &lt;/LI&gt;
&lt;LI&gt;Optimized:&amp;nbsp; this mode will tell the GC to only collect if it determines that a collection will be productive.&amp;nbsp; In this case, “productive” is determined by a number of factors, including amount of memory considered garbage, heap fragmentation, etc.&amp;nbsp; The exact formula is subject to change between CLR releases.&amp;nbsp; If the GC decides a collection will not be productive, then the call will have no effect.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;When should we use these new modes?&lt;/P&gt;
&lt;P&gt;Calling GC.Collect is generally discouraged, but as Rico points out &lt;A class="" href="http://blogs.msdn.com/ricom/archive/2004/11/29/271829.aspx" mce_href="http://blogs.msdn.com/ricom/archive/2004/11/29/271829.aspx"&gt;here&lt;/A&gt;, there are legitimate circumstances where you know there is a large number of objects you’ll never need again.&amp;nbsp; For example, at the end of a game level, when a custom Form is closed, or when a web form is finished, there may be a number of long-lived objects in generation 2 that are now dead.&amp;nbsp; By calling an Optimized collection at this point you give the GC a chance to evaluate the heap, and have it decide if a collection will free enough memory to be worth it. &lt;/P&gt;
&lt;P&gt;Forced and Default modes should generally only be used for debugging or testing scenarios, where you want to ensure objects are collected at a certain point in your application, or want to compare performance data.&amp;nbsp; In future versions of the CLR, there may be new guidance for using Default, but for now, its use is discouraged.&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1831076" width="1" height="1"&gt;</content><author><name>clyon</name><uri>http://blogs.msdn.com/clyon/ProfileUrlRedirect.ashx</uri></author><category term="GC" scheme="http://blogs.msdn.com/b/clyon/archive/tags/GC/" /><category term="Orcas" scheme="http://blogs.msdn.com/b/clyon/archive/tags/Orcas/" /></entry><entry><title>New In Orcas Part 1: What we’ve been doing</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/clyon/archive/2007/03/05/new-in-orcas-part-1-what-we-ve-been-doing.aspx" /><id>http://blogs.msdn.com/b/clyon/archive/2007/03/05/new-in-orcas-part-1-what-we-ve-been-doing.aspx</id><published>2007-03-06T08:14:00Z</published><updated>2007-03-06T08:14:00Z</updated><content type="html">&lt;P&gt;The &lt;A class="" href="http://www.microsoft.com/downloads/details.aspx?familyid=281fcb3d-5e79-4126-b4c0-8db6332de26e&amp;amp;displaylang=en" mce_href="http://www.microsoft.com/downloads/details.aspx?familyid=281fcb3d-5e79-4126-b4c0-8db6332de26e&amp;amp;displaylang=en"&gt;Orcas March CTP&lt;/A&gt;&amp;nbsp;is out, and what does that mean for the Garbage Collector?&amp;nbsp; The GC team has been concentrating on three areas for this release:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Bug fixes.&amp;nbsp; For Orcas, we’ve fixed several premature Out of Memory bugs, improved stability in certain stressful conditions, and even improved performance in some scenarios.&amp;nbsp;&amp;nbsp; &lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A class="" href="http://blogs.msdn.com/clyon/archive/2007/03/07/new-in-orcas-part-2-gc-collection-modes.aspx" mce_href="http://blogs.msdn.com/clyon/archive/2007/03/07/new-in-orcas-part-2-gc-collection-modes.aspx"&gt;GC Collection Modes&lt;/A&gt;.&amp;nbsp; We’ve added a new overload to System.GC.Collect that takes a System.GCCollectionMode enum, which allows the user to either force a collection or allow the GC to decide if a collection would be productive.&lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A class="" href="http://blogs.msdn.com/clyon/archive/2007/03/12/new-in-orcas-part-3-gc-latency-modes.aspx" mce_href="http://blogs.msdn.com/clyon/archive/2007/03/12/new-in-orcas-part-3-gc-latency-modes.aspx"&gt;GC Latency Modes&lt;/A&gt;.&amp;nbsp; A new GC feature that allows the user to specify blocks of code that are time-sensitive, and the GC will minimize its intrusiveness.&amp;nbsp;&amp;nbsp; This has been implemented as new properties on the System.Runtime.GCSettings class.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;In my next few blog entries I’ll go into more detail on our new features, including code samples and best practices.&lt;BR&gt;&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1814520" width="1" height="1"&gt;</content><author><name>clyon</name><uri>http://blogs.msdn.com/clyon/ProfileUrlRedirect.ashx</uri></author><category term="GC" scheme="http://blogs.msdn.com/b/clyon/archive/tags/GC/" /><category term="Orcas" scheme="http://blogs.msdn.com/b/clyon/archive/tags/Orcas/" /></entry><entry><title>When GC.KeepAlive Doesn’t</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/clyon/archive/2006/08/28/728688.aspx" /><id>http://blogs.msdn.com/b/clyon/archive/2006/08/28/728688.aspx</id><published>2006-08-28T21:05:00Z</published><updated>2006-08-28T21:05:00Z</updated><content type="html">&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;The purpose of GC.KeepAlive(Object) is to tell the GC not to collect an object until a certain point.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example:&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;BLOCKQUOTE dir=ltr style="MARGIN-RIGHT: 0px"&gt;
&lt;P class=MsoNormal dir=ltr style="MARGIN: 0in 0in 10pt"&gt;&lt;o:p&gt;&lt;FONT face=Calibri&gt;&lt;/FONT&gt;&lt;/o:p&gt;&lt;FONT face="Courier New" size=2&gt;class MyObject&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;~MyObject()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;Console.WriteLine(“MyObject Finalized”);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal dir=ltr style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;public static void Main()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MyObject obj = new MyObject();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LongRunningMethod();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;GC.KeepAlive(obj); // ~MyObject will NOT be run before this call&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;...&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;KeepAlive will ensure ~MyObject will not get run before LongRunningMethod gets called.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is useful if the long running method passes the object out to unmanaged code, for example.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In that case, you’ll want to keep the object from being collected by the GC until the method returns.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;What’s the secret to KeepAlive?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Nothing.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It’s just a normal method with no side effects except holding a reference to an object.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Since it holds a reference, the JIT considers the object rooted until that point (if no other reference to this object exists and if you are not in debuggable code), and the GC will not collect it.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;So when does KeepAlive not keep an object alive?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When it’s not called.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Ok, that was deliberately cryptic, let me illustrate using the MyObject class above:&lt;/FONT&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;BLOCKQUOTE dir=ltr style="MARGIN-RIGHT: 0px"&gt;
&lt;P class=MsoNormal dir=ltr style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face="Courier New"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;public static void Main()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;MyObject obj = new MyObject();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;while (true)&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;GC.Collect(); // force a collection to illustrate&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;GC.KeepAlive(obj);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;...&lt;BR&gt;}&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P class=MsoNormal dir=ltr style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;One would expect that when run, there would be nothing printed to the screen, since KeepAlive keeps obj from getting collected.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But since KeepAlive is after a while(true) loop it’s actually unreachable.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Compiling the code will give you compiler warning CS0162: Unreachable code detected on the GC.KeepAlive(obj) line.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Since KeepAlive is not even being called, obviously it won’t hold the object live. However if you compile the code in debug mode, the JIT will extend lifetimes of references to the end of their enclosing method.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In this case, KeepAlive actually isn’t necessary.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But in the release case, a reference should be live until the last line of code that references it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So why is obj getting finalized?&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;Looking at the IL for Main, we see what happened:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;BLOCKQUOTE dir=ltr style="MARGIN-RIGHT: 0px"&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face="Courier New" size=2&gt;.method public hidebysig static void&amp;nbsp; Main() cil managed&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; .entrypoint&lt;BR&gt;&amp;nbsp; // Code size&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 21 (0x15)&lt;BR&gt;&amp;nbsp; .maxstack&amp;nbsp; 1&lt;BR&gt;&amp;nbsp; .locals init ([0] class MyObject obj,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [1] bool CS$4$0000)&lt;BR&gt;&amp;nbsp; IL_0000:&amp;nbsp; nop&lt;BR&gt;&amp;nbsp; IL_0001:&amp;nbsp; newobj&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; instance void MyObject::.ctor()&lt;BR&gt;&amp;nbsp; IL_0006:&amp;nbsp; stloc.0&lt;BR&gt;&amp;nbsp; IL_0007:&amp;nbsp; br.s&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IL_0011&lt;BR&gt;&amp;nbsp; IL_0009:&amp;nbsp; nop&lt;BR&gt;&amp;nbsp; IL_000a:&amp;nbsp; call&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; void [mscorlib]System.GC::Collect()&lt;BR&gt;&amp;nbsp; IL_000f:&amp;nbsp; nop&lt;BR&gt;&amp;nbsp; IL_0010:&amp;nbsp; nop&lt;BR&gt;&amp;nbsp; IL_0011:&amp;nbsp; ldc.i4.1&lt;BR&gt;&amp;nbsp; IL_0012:&amp;nbsp; stloc.1&lt;BR&gt;&amp;nbsp; IL_0013:&amp;nbsp; br.s&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IL_0009&lt;BR&gt;} // end of method MyObject::Main&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=Tahoma size=2&gt;Since the code after the while loop is considered dead, the compiler has actually not built it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So the call to KeepAlive was optimized away, and is never actually called by the runtime.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The JIT then thinks it is no longer reachable after the while loop, and the GC is free to collect it.&lt;/FONT&gt;&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=728688" width="1" height="1"&gt;</content><author><name>clyon</name><uri>http://blogs.msdn.com/clyon/ProfileUrlRedirect.ashx</uri></author><category term="GC" scheme="http://blogs.msdn.com/b/clyon/archive/tags/GC/" /></entry><entry><title>WeakReferences And Tracking Resurrection</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/clyon/archive/2006/05/01/588001.aspx" /><id>http://blogs.msdn.com/b/clyon/archive/2006/05/01/588001.aspx</id><published>2006-05-02T03:23:00Z</published><updated>2006-05-02T03:23:00Z</updated><content type="html">&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;The WeakReference class has two public constructors.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 0.5in"&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;public WeakReference(Object target)&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 0.5in"&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;public WeakReference(Object target, bool trackResurrection)&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;The first parameter is pretty obvious.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It’s the object you want the WeakReference to reference, without keeping the object alive.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If a WeakReference is the only thing referencing an object, then the GC is free to collect the object.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;After the GC collects the object, WeakReference.IsAlive will return false, and WeakReference.Target will return null.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The WeakReference loses its handle to the object as soon as the GC collects it but before the finalizer (if any) gets run.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is called a short WeakReference.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;If the caller passes true as the trackResurrection parameter, then the WeakReference tracks the object’s life until finalization is complete.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is called a long WeakReference.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If the object is resurrected, a long WeakReference will continue to reference it, where a short WeakReference will report it as dead.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;The same distinction also applies to GCHandleType.Weak.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=588001" width="1" height="1"&gt;</content><author><name>clyon</name><uri>http://blogs.msdn.com/clyon/ProfileUrlRedirect.ashx</uri></author><category term="WeakReferences" scheme="http://blogs.msdn.com/b/clyon/archive/tags/WeakReferences/" /></entry><entry><title>Object Resurrection</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/clyon/archive/2006/04/25/583698.aspx" /><id>http://blogs.msdn.com/b/clyon/archive/2006/04/25/583698.aspx</id><published>2006-04-26T03:38:00Z</published><updated>2006-04-26T03:38:00Z</updated><content type="html">&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;I’m sure many of you have heard the term “object resurrection” with respect to the GC.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It’s an interesting (but not very useful) way to illustrate object lifetimes and the role of finalization versus garbage collection.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Basically, it’s a way to reference an object that has been finalized.&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;Here’s a rough description of how object resurrection can occur:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;OL style="MARGIN-TOP: 0in" type=1&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l0 level1 lfo1; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;A finalizable object is created.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It reachable from user code and is considered “live”.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l0 level1 lfo1; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;Inside the object’s finalizer is a statement assigning the “this” pointer to a global object (like a static).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Since it has a finalizer, a reference to the object is put on the finalization watchlist by the GC.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l0 level1 lfo1; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;At some point the object’s last strong reference is gone, the object is considered garbage. The object reference is then moved off the finalization watchlist and onto the freachable queue. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;Now the object is considered live again since it’s referred to by the freachable queue. and the object is considered “freachable”.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l0 level1 lfo1; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;When the finalizer thread runs the object’s finalizer, the object is removed from the freachable queue.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The global object now points to the object, making it once again reachable from user code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The object is said to have been “resurrected” and is once again reachable from user code and considered “live”.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;Here’s a code sample to illustrate:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;public class ResurrectedObj&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;~ResurrectedObj()&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;// this will resurrect the object by assigning &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;// it to the static reference&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;resurrectedReference = this;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;public static ResurrectedObj resurrectedReference = null;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;public static void &lt;?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" /&gt;&lt;st1:place w:st="on"&gt;Main&lt;/st1:place&gt;()&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ResurrectedObj liveReference = new ResurrectedObj();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;liveReference = null;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;GC.Collect(); &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;// liveReference is now dead and the object is put on the &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;// freachable queue&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;GC.WaitForPendingFinalizers();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;// at this point, the object previously referenced &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;// by liveReference is held alive by resurrectedReference&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;Unfortunately there are several implications to object resurrection which may not be immediately obvious.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For these reasons we strongly recommend against resurrecting objects.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in" type=disc&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l1 level1 lfo2; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;Once the object has been resurrected, the GC has removed it from the finalization queue.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This means when the object dies again, the finalizer will not be run a second time.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;To ensure the finalizer gets run, a call to GC.ReRegisterForFinalization() is required.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l1 level1 lfo2; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;Attempting to use an object after the finalizer has been run, can result in undefined behavior.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Maybe the finalizer released an unmanaged resource, and you try to access it?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is the same reason why you are discouraged from accessing other managed objects from a finalizer: that object’s finalizer may have been run before yours.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l1 level1 lfo2; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;Any object referenced by your resurrected object will also be resurrected.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If any of those objects are finalizable, their finalizers may have been run, and may be in an invalid state.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-list: l1 level1 lfo2; tab-stops: list .5in"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;As with all finalizable objects, multiple garbage collections are required to completely clean up the object, potentially hurting performance and memory usage.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=583698" width="1" height="1"&gt;</content><author><name>clyon</name><uri>http://blogs.msdn.com/clyon/ProfileUrlRedirect.ashx</uri></author><category term="GC" scheme="http://blogs.msdn.com/b/clyon/archive/tags/GC/" /></entry><entry><title>Why You Shouldn’t Rely On WeakReference.IsAlive</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/clyon/archive/2006/04/20/580255.aspx" /><id>http://blogs.msdn.com/b/clyon/archive/2006/04/20/580255.aspx</id><published>2006-04-21T03:34:00Z</published><updated>2006-04-21T03:34:00Z</updated><content type="html">&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The WeakReference class has the property IsAlive.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The problem with it, is that you can only trust it if it returns false.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;While a WeakReference points to an object that is either live (reachable), or garbage (unreachable) that has not yet been collected by the GC, the IsAlive property will return true.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;After an object has been collected, if the WeakReference is short (or if the target object does not have a finalizer) then IsAlive will return false.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Unfortunately by the time IsAlive returns, the target may have been collected.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;This situation can occur because of the way the GC suspends all managed threads before scanning the heap for garbage and collects it (this is an oversimplified explanation for illustrative purposes).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The GC can run at any time between two instructions.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman"&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;Foo f = new Foo();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;WeakReference wr = new WeakReference(f);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;// code goes here ...&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;if (wr.IsAlive)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;// Garbage Collection may have occurred here!&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Foo f2 = (Foo)wr.Target;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Console.WriteLine(f2.ToString());&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman"&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;If a collection occurred inside the if block, but before the WriteLine, this code would throw a NullReferenceException, since there are no live strong references to f.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The only reliable information IsAlive can give you, is that the object is no longer alive since once it’s dead, it’s dead (even resurrecting the target won’t make IsAlive return true once it thinks the object is dead).&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The correct pattern for the above code looks like this:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman"&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;Foo f = new Foo();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;WeakReference wr = new WeakReference(f);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;// code goes here...&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;Foo f2 = (Foo)wr.Target; // new strong reference&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;if (f2!=null)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Console.WriteLine(f2.ToString());&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman"&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;So how is IsAlive useful at all?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You could imagine implementing a cache by using a collection of WeakReferences, and using the IsAlive property to determine if an object still exists, and if not, replenish the cache.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Just be careful to only make decisions based on IsAlive returning false.&lt;/FONT&gt;&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=580255" width="1" height="1"&gt;</content><author><name>clyon</name><uri>http://blogs.msdn.com/clyon/ProfileUrlRedirect.ashx</uri></author><category term="WeakReferences" scheme="http://blogs.msdn.com/b/clyon/archive/tags/WeakReferences/" /></entry><entry><title>New Dispose Guidelines</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/clyon/archive/2005/04/14/408243.aspx" /><id>http://blogs.msdn.com/b/clyon/archive/2005/04/14/408243.aspx</id><published>2005-04-14T23:39:00Z</published><updated>2005-04-14T23:39:00Z</updated><content type="html">&lt;P&gt;Joe Duffy has posted the revised &lt;A href="http://www.bluebytesoftware.com/blog/PermaLink.aspx?guid=88e62cdf-5919-4ac7-bc33-20c06ae539ae"&gt;Dispose, Finalization, and Resource Management&lt;/STRONG&gt; Design Guideline&lt;/A&gt;. It's a great (and long) read. Check it out! &lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=408243" width="1" height="1"&gt;</content><author><name>clyon</name><uri>http://blogs.msdn.com/clyon/ProfileUrlRedirect.ashx</uri></author><category term="Dispose" scheme="http://blogs.msdn.com/b/clyon/archive/tags/Dispose/" /></entry><entry><title>The Truth About GCHandles</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/clyon/archive/2005/03/18/398795.aspx" /><id>http://blogs.msdn.com/b/clyon/archive/2005/03/18/398795.aspx</id><published>2005-03-18T20:43:00Z</published><updated>2005-03-18T20:43:00Z</updated><content type="html">&lt;p&gt;I've heard several people asking why GCHandle doesn't implement IDisposable, considering it wraps an unmanaged resource (a handle) and needs to be explicitly freed (using GCHandle.Free()). Before I explain the reason, I want to give a little background on GCHandles and their dangers. &lt;/p&gt; &lt;p&gt;What's a GCHandle? &lt;/p&gt; &lt;p&gt;A GCHandle is a struct that contains a handle to an object. It's mainly used for holding onto a managed object that gets passed to the unmanaged world to prevent the GC from collecting the object. You can also create a Pinned GCHandle to a managed object and retrieve the object's address in memory. &lt;/p&gt; &lt;p&gt;How are GCHandles dangerous? &lt;/p&gt; &lt;p&gt;When you create a new GCHandle, a new entry in the AppDomain's handle table is created. This entry is kept until the handle is freed (via GCHandle.Free()) or the AppDomain is unloaded. &lt;/p&gt; &lt;p&gt;Things get tricky if you were to make a copy of a GCHandle: &lt;/p&gt; &lt;p class="code"&gt;Object obj = new Object();&lt;br /&gt;GCHandle gch = GCHandle.Alloc(obj, GCHandleType.Normal);&lt;br /&gt;GCHandle gch2 = gch;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;Since GCHandle is value type, gch2 has its own copy of the handle. You now have two handles that point to the same entry in the handle table. Unfortunately, since gch2 is a copy of –not a reference to– gch, anything that happens to gch doesn't happen to gch2. For example, calling gch.Free() will delete the entry from the handle table, but not update gch2, so gch2.IsAllocated will return true, but gch2.Target will be null. The same problem arises with casting to and from IntPtrs, and when GCHandles get boxed. Unlike double-freeing a single GCHandle, freeing the copy will NOT throw an InvalidOperationException. You have to be very careful not to double-Free your handles since this can corrupt the handle table. &lt;/p&gt; &lt;p&gt;Why don't GCHandles implement IDisposable? &lt;/p&gt; &lt;p&gt;One of the main purposes of IDisposable to avoid the use of finalizers. This is because finalizers are not run deterministically, and result in promoting a finalizable object a generation, effectively keeping in memory longer. Since GCHandle is a value type, it has no finalizer, and is not collected by the GC, so these problems are eliminated. Another other main use of IDisposable is to clean up unmanaged resources as soon as you are done with them. With a GCHandle, the resource is the handle which is cleaned up by calling GCHandle.Free(). If Free isn't called, the handle gets cleaned up when the appdomain is unloaded. &lt;/p&gt; &lt;p&gt;One of the side effects of having a struct implement IDisposable, is that users may be tempted to cast their GCHandles as IDisposable, which boxes the GCHandle into an IDisposable object on the heap, and the two GCHandles get out-of-sync. The same problem arises with the putting a disposable struct into a using block: &lt;/p&gt; &lt;p class="code"&gt;struct Test : IDisposable&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public bool disposed; // initialized to false&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public void Dispose()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;disposed = true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void Foo()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Test t = new Test();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;using (t)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// do stuff&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (!t.disposed)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;t.Dispose();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/p&gt; &lt;p&gt;t.disposed will return false, since it was a copy of t whose Dispose method was called. If t were a GCHandle, then the handle would be removed from the appdomain's handle table, and calling Free after the using would result in a double Free, even though IsAllocated would return true! &lt;/p&gt; &lt;p&gt;Remember, GCHandles are advanced structures, and one should be very careful to ensure they are cleaned up properly. Unfortunately, IDisposable makes it easy to get this wrong, so the BCL designers erred on the side of caution, and gave GCHandle a Free() method to use. &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=398795" width="1" height="1"&gt;</content><author><name>clyon</name><uri>http://blogs.msdn.com/clyon/ProfileUrlRedirect.ashx</uri></author><category term="Dispose" scheme="http://blogs.msdn.com/b/clyon/archive/tags/Dispose/" /><category term="GCHandles" scheme="http://blogs.msdn.com/b/clyon/archive/tags/GCHandles/" /></entry></feed>