This blog has moved!

Check out www.CodeBetter.com/blogs/grant.killian

<July 2008>
SuMoTuWeThFrSa
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789


Navigation

Professional Props...

Extracurricular Props...

Subscriptions

Article Categories



Friday, January 23, 2004 - Posts

Using the GC

I tackled Garbage Collection last year here and even here.  Let me add a little more to the subject, prompted by an emaiI I got from a buddy.  If I create sample windows project with a single button on the form and add the following code . . .

 private void button1_Click(object sender, System.EventArgs e)
  {
   TestObj obj = new TestObj();
   obj.WriteSomethin( "text" );
   GC.Collect();
   GC.WaitForPendingFinalizers();
   doStuff();
  }

  private void doStuff()
  {
   for ( int n = 1;  n <= 5; n++ )
   {
    System.Threading.Thread.Sleep( 1000 ); //simulate long running operation
    System.IO.StreamWriter sw = new System.IO.StreamWriter( @"C:\Test.log", true );//append to file
    sw.WriteLine( "Iteration " + n );
    sw.Close();
   }
  }
 }

 public class TestObj : IDisposable
 {
  ~TestObj()
  {
   AllDone();
  }
  public void Dispose()
  {
   AllDone();
  }
  private void AllDone()
  {
   System.IO.StreamWriter sw = new System.IO.StreamWriter( @"C:\Test.log", true );//append to file
   sw.WriteLine( "TestObj Destroyed " + System.DateTime.Now.ToShortTimeString() );
   sw.Close();
  }
  public void WriteSomethin( string strStuff )
  {
   System.IO.StreamWriter sw = new System.IO.StreamWriter( @"C:\Test.log", true );//append to file
   sw.WriteLine( strStuff );
   sw.Close();
  }
 }

If you run it, click button1, and check out C:\Test.log BEFORE closing the application you'll get this:

text
Iteration 1
Iteration 2
Iteration 3
Iteration 4
Iteration 5

It looks like our Destructor doesn't fire because no “TestObj Destroyed” message is in the file, even though the method has gone out of scope.  Only by closing the application does the Destructor actually fire (and log “TestObj Destroyed 5:03 PM”) -- all this even with our statements:

   GC.Collect();
   GC.WaitForPendingFinalizers();

Which should “empty the finalizers” queue and trigger our GC.  It doesn't trigger TestObj destruction; the important point is that I don't have control over exactly when my object will be collected by the runtime.

Add a second button to the form and place this code in the code-behind:

  private void button2_Click( object sender, System.EventArgs e )
  {
   using( TestObj obj = new TestObj() )
   {
    obj.WriteSomethin( "text" );
   }
   doStuff();
  }

Run the app and click the second button.  “Hold on!“ you might say, it looks like it's disposing multiple TestObj objects because we get multiple “TestObj Destroyed 5:03 PM” messages; not to worry, comment out the explicit c# destructor (the “~TestObj” function) so that our object only writes a message once upon object finalization.  Then run the application and check the log file:

text
TestObj Destroyed 5:13 PM
Iteration 1
Iteration 2
Iteration 3
Iteration 4
Iteration 5

Much better.  The more control I have, the happier I am.  Our TestObj is destroyed upon the termination of our using() statement scope.  Plus, button2_click doesn't explicitly call GC.Collect and GC.WaitForPendingFinalizers -- unless you have a really good reason, it's unwise to call these methods.  Letting the .Net Framework manage the memory is usually preferred.

For more on GC, including a bit on WeakReferences, check out the MSDN articles: http://msdn.microsoft.com/msdnmag/issues/1100/gci/
http://msdn.microsoft.com/msdnmag/issues/1200/GCI2/

Happy .Netting

posted Friday, January 23, 2004 2:22 PM by grant.killian

The good ol' days of Response.Write and Server.CreateObject

One of the many projects I'm working is an ASP classic app; we're extending it with new ASPX functionality, which is interesting in its own right, but as I peruse the ASP codebase I'm constantly struck by how primitive old school ASP feels compared to developing for the .Net framework. 

With ASP, a modest form of object orientation (through VBScript Classes) and code reuse is achieved through this web of include files.  I remember doing my share of this development back in the day, and considered it cutting edge then; we created some sophisticated stuff!  Around 1998-1999, me and a colleague had this cool idea where we'd place all our logic in COM components for ease of debugging (remember trying to debug in InterDev on a remote server?) and compiled performance -- plus, we'd be able to reuse DLLs easier than a convoluted web of include files.  We took the idea further, and called it “VBML” where we'd have proprietary tags (“<VBTABLE src="“tblDataBaseUsers“/">” etc.) that rendered as special content (all generated by our COM components); every asp page would run through our proprietary “magic parser.”  100% generated HTML.  We had MTS rolling, SQL Server, and thought this was as brilliant as beer in a bottle!

In retrospect, we were marching down the same path as the Microsoftians.  Our VBML never took final shape, it was always a work in progress with lots of theoretical elements we never got around to implementing.  Thank goodness Microsoft did --  and then some.  The .Net platform introduced powerful elements like the cache, viewstate, and a new Page processing model our VBML hardly anticipated -- us amateurs were barely scratching the surface!

Anyway, I think all that ASP classic experience, the VBML years included, serves me well.  I understand the underpinnings of the .Net framework and appreciate the measures it takes to ensure proper component versioning, etc.  People new to .Net, without the hard-earned perspective many years of Response.Write and Server.CreateObject() provide, are at a serious disadvantage when doing more sophisticated .Net development.  Experience counts for a lot in this industry, even if it's in a different platform or language!

Happy .Netting!

posted Friday, January 23, 2004 8:10 AM by grant.killian




Powered by Dot Net Junkies, by Telligent Systems