Wednesday, May 05, 2004 1:27 PM
pdbartlett
Resurrection is not ALWAYS bad
[UPDATED: On the way home I remembered the Environment.ShutdownStarted property, and an unrelated visit to Brad Abrams blog both confirmed this to be what I needed and reminded me that this post had "unfinished business"]
I've recently been skimming through an office copy of Jeffrey Richter's "Applied .NET Framework Programming", and have been very impressed. Though much of it was already known to me, this is more indicative of how easy to understand the .NET programming model (generally) is, rather than criticism of the level at which the book is pitched.
However, one thing that I definitely did not know was that there is a valid, non-contrived (and rather neat if you ask me :) use for resurrection. See if you can figure out what's going on in the code below, which is "inspired" by an example in the book:
using System;
using System.Collections;
namespace PoolTest
{
class PooledObject
{
// static members
private static ArrayList s_pool;
static PooledObject()
{
s_pool = new ArrayList();
s_pool.Add(new PooledObject());
s_pool.Add(new PooledObject());
s_pool.Add(new PooledObject());
}
public static PooledObject GetObject()
{
int c = (s_pool == null) ? 0 : s_pool.Count;
if (c == 0)
return new PooledObject();
PooledObject o = (PooledObject)s_pool[c-1];
s_pool.RemoveAt(c-1);
return o;
}
// instance members
public PooledObject()
{
Console.WriteLine("Created an object");
}
~PooledObject()
{
if (Environment.ShutdownStarted == false && s_pool != null)
{
Console.WriteLine("Returning object to pool");
s_pool.Add(this);
GC.ReRegisterForFinalize(this);
}
else
{
Console.WriteLine("Pool no longer exists - object will be destroyed");
}
}
}
public class EntryPoint
{
static void Main()
{
Console.WriteLine("Entered Main()");
Console.WriteLine("Getting object 1");
PooledObject o1 = PooledObject.GetObject();
Console.WriteLine("Getting object 2");
PooledObject o2 = PooledObject.GetObject();
Console.WriteLine("Getting object 3");
PooledObject o3 = PooledObject.GetObject();
Console.WriteLine("Getting object 4");
PooledObject o4 = PooledObject.GetObject();
Console.WriteLine("Getting object 5");
PooledObject o5 = PooledObject.GetObject();
Console.WriteLine("Releasing object 1");
o1 = null;
Console.WriteLine("Releasing object 2");
o2 = null;
Console.WriteLine("Releasing object 3");
o3 = null;
Console.WriteLine("Releasing object 4");
o4 = null;
Console.WriteLine("Releasing object 5");
o5 = null;
// for illustration only - wouldn't really do this
Console.WriteLine("Forcing a collection");
GC.Collect();
Console.WriteLine("Leaving Main()");
}
}
}
And the answer is: object pooling without the need for COM+/EnterpriseServices.
Thanks Jeff - a great example from a great book!