garbage collection

  • Thread starter Thread starter Guest
  • Start date Start date
yes it seems interesting, but in respect to our discussion, finalizer or
desctructor does not call Dispose (at least destructor doesnt have to.).

one more interesting thing. compile and run that code. and see that it
definetly works!!
 
The destructor is the finalizer. And the object will be destroyed when
Finalize() is called by the GC. Not before. Setting a field or variable to
null has no effect on the object it references. It is a pointer. You just
point it somewhere else. The object is unaffected.

--
HTH,

Kevin Spencer
Microsoft MVP
..Net Developer
Ambiguity has a certain quality to it.
 
Brian,

Right, the cases that the Finalizer doesn't run at all are rare, but you
would be supprised how many times I've seen it happen in scenarios where COM
interop is used on threads that are failing to pump the windows message
queue, or in Finalize methods that make blocking calls in unmanaged code
:-(.
Indeed, Constrained execution regions (CER's) are a great addition to the
framework, and a great tool in hosted environments.
Willy.
 
Kevin,
The Finalize method is called on ran on the "finalizer" thread (an high
priority thread) after the GC has done it's marks/sweep run, but this
decision is mabe by the EE not directly by the GC, and only when there are
finalizable objects in the "ready for finalization" queue, when no such
objects are queued, the finalizer thread is not started (why would it?).

Willy.
 
Technically true, but you might as well say that an ignition key doesn't
cause exhaust fumes to exit the exhaust pipe of a car. It's a chain of
events that is all about Garbage Collection, and initialized by Garbage
Collection. In the context of this discussion, we're talking about objects
(Sockets) which WILL be finalized. The technical details are not
particularly relevant to this particular discussion. It all started with the
OP asking why his class was accumulating memory, and when told that he
needed to Dispose Sockets, he wanted to know why. Maybe I'm too concerned
with results. I do have my times of pure technological research, and it is
certainly worthwhile. However, those times don't occur when I'm trying to
debug something!

--
;-),

Kevin Spencer
Microsoft MVP
..Net Developer
Ambiguity has a certain quality to it.
 
i think you didnt read the code example. here it is :

using System;
using System.ComponentModel;

public class DisposeExample
{
public class MyResource: IDisposable
{
private IntPtr handle;
private Component component = new Component();
private bool disposed = false;


public MyResource(IntPtr handle)
{
this.handle = handle;
}

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

private void Dispose(bool disposing)
{
if(!this.disposed)
{
if(disposing)
{
component.Dispose();
}

CloseHandle(handle);
handle = IntPtr.Zero;
}
disposed = true;
}

[System.Runtime.InteropServices.DllImport("Kernel32")]
private extern static Boolean CloseHandle(IntPtr handle);

~MyResource()
{
Dispose(false); // This line is very important.... someone can
not include it.
}
}
public static void Main()
{
// Insert code here to create
// and use the MyResource object.
}
}
 
Hmm...I suppose it's me you are replying to, right?
When a class implement IDisposable it better adheres to the disposable
pattern, that is, a type that implements IDisposable should also have a
finalizer (called a destructor in C#), and that finalizer should call
Dispose(false).

But this is not my point, my point is that you should call dispose() when
you are done with the object if you want deterministic release of the
underlying resources, relying on finalize (your destructor ~) to call
Dispose(false) gives you non deterministic release, and should be avoided,
it's just a safety net to handle the cases that someone forgets to call
Dispose().

That's why I implement it as:

~MyResource()
{
Debug.Writeline("BUG... you should call dispose instead of
relying on the finalizer");
Dispose(false);
}

I'm also not clear on what you mean by this:
// This line is very important.... someone can not include it.
Guess you meant something like this:
// This line is very important.... someone can not omit it.

Willy.

PS. Note the difference between Dispose() and Dispose(bool), in my replies?
the first must be called explicitely, the second is called by the finalize
methods (when the finalizer runs).


The Crow said:
i think you didnt read the code example. here it is :

using System;
using System.ComponentModel;

public class DisposeExample
{
public class MyResource: IDisposable
{
private IntPtr handle;
private Component component = new Component();
private bool disposed = false;


public MyResource(IntPtr handle)
{
this.handle = handle;
}

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

private void Dispose(bool disposing)
{
if(!this.disposed)
{
if(disposing)
{
component.Dispose();
}

CloseHandle(handle);
handle = IntPtr.Zero;
}
disposed = true;
}

[System.Runtime.InteropServices.DllImport("Kernel32")]
private extern static Boolean CloseHandle(IntPtr handle);

~MyResource()
{
Dispose(false); // This line is very important.... someone can
not include it.
}
}
public static void Main()
{
// Insert code here to create
// and use the MyResource object.
}
}
 
Jon Skeet said:
As far as I can see, it *is* called when it's finalized.

This short program demonstrates that:

using System;
using System.Net.Sockets;

public class Test : Socket
{
public Test(AddressFamily addressFamily,
SocketType socketType,
ProtocolType protocolType)
: base (addressFamily, socketType, protocolType)
{
}

protected override void Dispose (bool disposing)
{
base.Dispose(true);
Console.WriteLine ("Disposed!");
}

static void Main()
{
Test t = new Test(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.IP);

t = null;
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine ("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 (ReleaseComObject 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 "finalizable 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.Sockets;
using System.Reflection;
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(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if(!this.disposed)
{
Marshal.ReleaseComObject(madDog);
GC.Collect();
GC.WaitForPendingFinalizers();
madDog= null;
Console.WriteLine ("Dog object Disposed!");
}
this.disposed = true;
}
~T()
{
Console.WriteLine ("Finalizing DogWrapper !");
Dispose(false);
}
}
public class Test : Socket
{
public Test(AddressFamily addressFamily,
SocketType socketType,
ProtocolType protocolType)
: base (addressFamily, socketType, protocolType)
{
}

protected override void Dispose (bool disposing)
{
base.Dispose(true);
Console.WriteLine ("Test Disposed!");
}
[STAThread]
static void Main()
{
T te = new T();
GC.Collect();
Console.WriteLine(te.GetVersion());
for (int i = 0; i < 10; i++)
{
Test t = new Test(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.IP);
GC.Collect();
System.Threading.Thread.Sleep(500);
}
Console.WriteLine ("Finishing");
}
}
 
Willy Denoyette said:
Hmm...I suppose it's me you are replying to, right?
When a class implement IDisposable it better adheres to the disposable
pattern, that is, a type that implements IDisposable should also have a
finalizer (called a destructor in C#), and that finalizer should call
Dispose(false).

Not all classes that implement IDisposable need a finalizer - indeed, I
would argue that *most* don't.

StreamReader is a good example of this - it implements IDisposable to
close the stream it wraps, but it doesn't need a finalizer because it
doesn't *directly* hold any unmanaged resources. Instead, it relies on
teh stream that it wraps having a finalizer.
 
then in our example, the socket wrapper class doesnt have to call dispose of
socket. because socket.Dispose() will be called by the runtime. (probably in
the same garbage collection run.) but what if the socket object in the
wrapper object referenced by another object outside of the wrapper object?
 
Jon Skeet said:
Not all classes that implement IDisposable need a finalizer - indeed, I
would argue that *most* don't.

StreamReader is a good example of this - it implements IDisposable to
close the stream it wraps, but it doesn't need a finalizer because it
doesn't *directly* hold any unmanaged resources. Instead, it relies on
teh stream that it wraps having a finalizer.

Agreed, but I was talking about base types, and - sorry about the
confusion - what I said is not what I meant.
What I meant to say was, that every type that has a finalizer should
implement IDisposable. This gives users of the type a means to perform
deterministic clean-up of the same resources which the finalizer is
responsible for.
Sure, you may also implement Dispose on types without finalizers, e.g when
transitively disposing of object state or when using types which manage
their resources with finalizers allready.
Note that value types are an exception because they can't have a finalizer,
but I think this is a very simple rule; If you have (say need) a finalizer,
you want Dispose().

Willy.
 

I forgot to say in my previous reply that StreamReader does not "implement"
IDisposable it just implements Dispose(bool) that calls it's base
(TextReader.Dispose(bool)) which implements IDisposable though.

Willy.
 
then in our example, the socket wrapper class doesnt have to call dispose of
socket. because socket.Dispose() will be called by the runtime. (probably in
the same garbage collection run.) but what if the socket object in the
wrapper object referenced by another object outside of the wrapper object?

A wrapper class shouldn't have a finalizer, but it *should* implement
IDisposable to allow the user to dispose of the "wrapped" resource
early.
 
Thanks everyone

Brad Wood said:
I believe this snippet:
<snip>
try
{
Encoding ASCII = Encoding.ASCII;
IPEndPoint hostEndPoint;
IPAddress hostAddress = System.Net.IPAddress.Loopback;
int conPort = port;
string Get = "GET / HTTP/1.1\r\nHost: 127.0.0.1\r\nConnection:
Close\r\n\r\n";

Byte[] ByteGet = ASCII.GetBytes(Get);
byte[] RecvBytes = new byte[256];
hostEndPoint = new IPEndPoint(hostAddress, conPort);
Socket s= new Socket(AddressFamily.InterNetwork, SocketType.Stream,
ProtocolType.Tcp);
s.Connect(hostEndPoint);
s.Send(ByteGet, ByteGet.Length, 0);

s.Close();


}
catch
{


}
</snip>

could be changed to:

<NewSnip>
Encoding ASCII = Encoding.ASCII;
IPEndPoint hostEndPoint;
IPAddress hostAddress = System.Net.IPAddress.Loopback;
int conPort = port;

Byte[] ByteGet = ASCII.GetBytes("GET / HTTP/1.1\r\nHost:
127.0.0.1\r\nConnection: Close\r\n\r\n");
byte[] RecvBytes = new byte[256];
hostEndPoint = new IPEndPoint(hostAddress, conPort);
using (Socket s= new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp))
{
s.Connect(hostEndPoint);
s.Send(ByteGet, ByteGet.Length, 0);
s.Shutdown();
// shouldn't need to call close explicitly; Dispose should handle this
// note that by using the using construct, Dispose is called.
}
</NewSnip>

The main reason you should implement IDispose in one of your own classes
is to ensure that unmanaged resources (Database connections is the
classic example) are released.
You might find this template helpful:
<ClassImplementingDispose>
class Billy: IDisposable
{
private bool mDisposed = false;

public void doStuff()
{
// do this in each public method in case user called dispose,
// but then tried to call another method
if ( mDisposed ) throw new ObjectDisposedException();
// do what you normally do.
}

/// <summary>
/// If SupressFinalize wasn't there, the gc would have to do all the
/// extra work that is required for objects in the finalization queue.
/// </summary>
public void Dispose()
{
Dispose( true );
GC.SuppressFinalize(this);
}

protected virtual void Dispose( bool disposing )
{
if ( disposing )
{
// dispose any dependant managed objects if necessary.
// You don't want this to happen when the GC is calling this code
// because you have no idea what state other objects would be in at
that point.
disposed = true;
}
// Free unmanaged resources here.
}

~Billy()
{
Dispose( false );
Debug.Assert(false, "You are using this object improperly. Create in
using construct or ensure to call Dispose()");
}
}
</ClassImplementingDispose>

André said:
Thanks Kevin,

Can you help me add the dispose interface?

This is my simple ping class......
 
Back
Top