"Jon Skeet [C# MVP]" <sk***@pobox.co m> wrote in message
news:MP******** *************** *@msnews.micros oft.com...
Willy Denoyette [MVP] <wi************ *@telenet.be> wrote: "The Crow" <q> wrote in message
news:OE******** ******@TK2MSFTN GP15.phx.gbl... > socket is managed, socket implements idisposable, so no matter when,
> when
> socket will be garbage collected (sure it will be), its Dispose()
> method
> will be called.why bother with idisposable? am i missing something?
Dispose is not called when the sockect is GC'd. Dispose must be called
explicitely.
As far as I can see, it *is* called when it's finalized.
This short program demonstrates that:
using System;
using System.Net.Sock ets;
public class Test : Socket
{
public Test(AddressFam ily addressFamily,
SocketType socketType,
ProtocolType protocolType)
: base (addressFamily, socketType, protocolType)
{
}
protected override void Dispose (bool disposing)
{
base.Dispose(tr ue);
Console.WriteLi ne ("Disposed!" );
}
static void Main()
{
Test t = new Test(AddressFam ily.InterNetwor k,
SocketType.Stre am,
ProtocolType.IP );
t = null;
GC.Collect();
GC.WaitForPendi ngFinalizers();
Console.WriteLi ne ("Finishing" );
}
}
Are you trying to stress the difference between something being GC'd
and something being finalized?
--
To further illustrate my point, following is a sample (based on yours) that
illustrates how easy it is to block the finalizer thread.
This sample includes a class DogWrapper that wraps a simple COM object Dog,
in Main I create an instance of Dog and calls a method on it.
The output (except ***) looks like:
Woef!!
Test Disposed!
Finalizing DogWrapper !
*** 5 seconds delay here (10 * 0.5 secs.)
Finishing
Dog object Disposed!
Test Disposed!
Test Disposed!
Test Disposed!
Test Disposed!
Test Disposed!
Test Disposed!
Test Disposed!
Test Disposed!
Test Disposed!
Notice the time when "Finishing" is output... at program exit time, but
before the finalizer runs! That means that from the moment on that the
"Finalizer thread" enters DogWrapper's Finalize (ReleaseComObje ct to be
precise) it will block until it gets aborted and restarted by the CLR at
process shutdown time.
Note that this doesn't stop the GC nor the program to run (but how long?),
however, you will leak the resources you intended to release through the
destructor calling Dispose(false) and your "finalizabl e instances" will
finally exhaust the GC heap.
Note that the same can happen if the finalizer thread gets stuck (or blocks
for a long time) in unmanaged code.
using System;
using System.Net.Sock ets;
using System.Reflecti on;
using System.Runtime. InteropServices ;
using Project; // IA for Dog
public class DogWrapper : IDisposable
{
Dog madDog;
public void Bark()
{
madDog= new Dog();
madDog.Bark();
}
public void Dispose()
{
this.Dispose(tr ue);
GC.SuppressFina lize(this);
}
protected virtual void Dispose(bool disposing)
{
if(!this.dispos ed)
{
Marshal.Release ComObject(madDo g);
GC.Collect();
GC.WaitForPendi ngFinalizers();
madDog= null;
Console.WriteLi ne ("Dog object Disposed!");
}
this.disposed = true;
}
~T()
{
Console.WriteLi ne ("Finalizing DogWrapper !");
Dispose(false);
}
}
public class Test : Socket
{
public Test(AddressFam ily addressFamily,
SocketType socketType,
ProtocolType protocolType)
: base (addressFamily, socketType, protocolType)
{
}
protected override void Dispose (bool disposing)
{
base.Dispose(tr ue);
Console.WriteLi ne ("Test Disposed!");
}
[STAThread]
static void Main()
{
T te = new T();
GC.Collect();
Console.WriteLi ne(te.GetVersio n());
for (int i = 0; i < 10; i++)
{
Test t = new Test(AddressFam ily.InterNetwor k,
SocketType.Stre am,
ProtocolType.IP );
GC.Collect();
System.Threadin g.Thread.Sleep( 500);
}
Console.WriteLi ne ("Finishing" );
}
}