When is Finalize() called?

C

Charles Law

I have an application that creates a class. The class has unmanaged
resources, so must end gracefully.

How can I guarantee that the unmanaged resources are freed?

I have looked at IDisposable, but this seems to rely on a call from the
application, e.g.

MyClass.Dispose()

and I don't wish to rely on the user of my class to call Dispose at the
right time.

I have looked at Finalize() but cannot get it to be called. I define it as

Protected Overrides Sub Finalize()

but it is not called when my class goes out of scope or when the application
ends.

What am I doing wrong?

Thanks.

Charles
 
C

Charles Law

Hi Ken

Thanks for the link, however, this appears to relate to COM and I am using
the Win32 API from managed code.

I am not using COM as such, but in my VB.NET class I open a file which must
be closed properly when the object is destroyed.

Is there a way to ensure this without relying on the caller to call a
Dispose() method?

Thanks.

Charles
 
J

Jay B. Harlow [MVP - Outlook]

Charles,
..NET does not support deterministic finalization!

I would suggest you implement the Finalize/Dispose pattern. Implement both
IDisposable & the Finalize method.

http://msdn.microsoft.com/library/d.../en-us/cpgenref/html/cpconFinalizeDispose.asp

Users of your class are "obligated" to call the Dispose method, if they
choose not to, then the Finalize method will take care of it.

How are you ending your application? Finalizers are not guaranteed to be
called when your application is exiting...

http://msdn.microsoft.com/library/d.../html/frlrfSystemObjectClassFinalizeTopic.asp

Hope this helps
Jay
 
H

Herfried K. Wagner [MVP]

* "Charles Law said:
Is there a way to ensure this without relying on the caller to call a
Dispose() method?

Close the file in the "finalizer" if the user hasn't already done that.
 
C

Charles Law

Hi Herfried

The problem I have is that the finalizer is not being called.

How and where should I declare it to ensure that it is called when my class
goes out of scope?

Thanks.

Charles
 
H

Herfried K. Wagner [MVP]

* "Charles Law said:
The problem I have is that the finalizer is not being called.

How and where should I declare it to ensure that it is called when my class
goes out of scope?

It won't be called when the object gets out of scope, but it will be
called...
 
C

Charles Law

That's not really going to be good enough for my needs. What happens when
the application ends? I'm finding that it still doesn't get called.

Is there another way?

Charles
 
A

Armin Zingler

Charles Law said:
That's not really going to be good enough for my needs. What happens
when the application ends? I'm finding that it still doesn't get
called.

You are right. I remember, when starting with .NET development, I also came
across this issue. There was a wrapper class for a NotifyIcon, and in the
class' finalize method, I called NotifyIcon.dispose - but finalize wasn't
called when the program ends.
Is there another way?

I tried this now:

sub main
'call startup object here
'...
gc.collect
end sub

Seems to work.
 
C

Charles Law

Hi Armin

This looks like it is relying on the _user_ of the class to call gc.collect.

In my application, an instance of my class can be created, and then go out
of scope. When it goes out of scope (i.e. the reference count goes to zero)
I need some method in the class to be called automatically so it can clean
up.

Any ideas?

Charles
 
A

Armin Zingler

Charles Law said:
This looks like it is relying on the _user_ of the class to call
gc.collect.

Yes, but only once without being forced to call Dispose for each object,
caused by the fact that finalize is not called when the program ends.
In my application, an instance of my class can be created, and then
go out of scope. When it goes out of scope (i.e. the reference count
goes to zero) I need some method in the class to be called
automatically so it can clean up.

Any ideas?

I only referred to the paragraph I quoted, i.e. to the problem that finalize
is not called when the app ends. In this case, calling gc.collect does the
job. (question to the group: is it necessary? Should finalize be called at
the end?)

Concerning variables running out of scope, there is AFAIK no solution. We
don't know when the object will be terminated (due to GC). If you want
resources to be cleaned up earlier, you can call Dispose. I think that's the
main reason why Dispose has been "invented".
 
C

Charles Law

Thanks for the clarification.

I wonder if anyone else has any thoughts on this?

If it were C++ then I would expect the class destructor to be called. Does
that mean that VB.NET is not fully OO in this respect?

Charles
 
L

Lee Gillie

It is my understanding that heap rundown at program end does not call the finalizers on the stack. It simply releases memory
consumed by objects as a single chunk. This is supposed to be a performance enhancement for .NET applications. You need to do a
Dispose, or Close, or something, that the object consumer calls when done. Otherwise you can not guarantee a clean rundown of
non-memory resources, such as open files, or other Win32 objects. There is nothing automatic I have been able to find, that you can
rely upon 100%, without the object consumer specifically calling SOMETHING that will release those resources. This adds the buren of
ensuring clean run down to the consumer. My research was a dissappointment for this long-time C++ coder. For this issue I have
relegated it to my "just live with it" list.

HTH - Lee Gillie, Spokane WA
 
C

Charles Law

Thanks Lee.

I don't know whether I am surprised or not, but this seems quite an omission
from VB.NET. I can't see the logic for not providing a destructor in VB.NET.

Ho hum!

Charles


Lee Gillie said:
It is my understanding that heap rundown at program end does not call the
finalizers on the stack. It simply releases memory
consumed by objects as a single chunk. This is supposed to be a
performance enhancement for .NET applications. You need to do a
Dispose, or Close, or something, that the object consumer calls when done.
Otherwise you can not guarantee a clean rundown of
non-memory resources, such as open files, or other Win32 objects. There is
nothing automatic I have been able to find, that you can
rely upon 100%, without the object consumer specifically calling SOMETHING
that will release those resources. This adds the buren of
ensuring clean run down to the consumer. My research was a dissappointment
for this long-time C++ coder. For this issue I have
 
J

Jay B. Harlow [MVP - Outlook]

Charles,
If it were C++ then I would expect the class destructor to be called. Does
that mean that VB.NET is not fully OO in this respect?
Huh????

Since when is deterministic finalization a feature of OO?

As my other posted pointed out:

..NET does not support deterministic finalization!

I would suggest you implement the Finalize/Dispose pattern. Implement both
IDisposable & the Finalize method.

http://msdn.microsoft.com/library/d.../en-us/cpgenref/html/cpconFinalizeDispose.asp

Users of your class are "obligated" to call the Dispose method, if they
choose not to, then the Finalize method will take care of it.

How are you ending your application? Finalizers are not guaranteed to be
called when your application is exiting...

http://msdn.microsoft.com/library/d.../html/frlrfSystemObjectClassFinalizeTopic.asp

Hope this helps
Jay
 
C

Charles Law

Hi Jay

Perhaps OO is the wrong expression, but I am referring to the concept of
encapsulation. To require Dispose to be called by the user of a service
implies that they know something about the internal operation of the
service, i.e. that it has unmanaged resources that need to be released.

Although you say that if they don't call Dispose the Finalize method will
take care of it, it is also the case that you cannot guarantee when the
Finalize method will be called (if at all, in the case of exiting the
program).

The situation I have is a main form that creates a class. This class opens a
serial port. It may open a second serial port, and may also open one and
close another.

When the reference count of the serial port class goes to zero (the object
reference goes out of scope) the port must be closed immediately. Otherwise,
if the user tries to open the port for another session it will fail because
the port is still open from the previous session.

I have read the articles you pointed to, but they basically confirm the
non-deterministic nature of the Finalize method.

I can see how the Dispose method allows the developer to force an object to
free its handles etc. but failure to do so would cause the serial class to
misbehave, which I want to avoid (as an implementor of the serial class).

I hope that all makes sense.

I suppose what I want is a method on the serial class that I can guarantee
will be called when the object reference goes out of scope. Then I can
recover in the event that the caller does not call Dispose.

As far as closing the application goes, the user clicks the Close button,
top right. In this case, because Finalize is not called, the serial class
keeps the application and debugger alive. This is because it starts a second
thread to read characters from the port asynchronously, which never gets
shut down.

Is there anything I can do about this, as the implementor of the serial
class?

Charles
 
J

Jay B. Harlow [MVP - Outlook]

Charles,
Perhaps OO is the wrong expression, but I am referring to the concept of
encapsulation.
I'm not so sure I would say that Deterministic Finalization is encapsulation
per se, although I follow your train of thought. In that the class itself
"knows" when it should be cleaned up, ergo the Finalize method. However
Deterministic refers to WHEN the class is allowed to clean up, not so much
that it does know how to or not ;-) However that is not really what the
problem here is, so we don't need to expend time on a largely academic
debate!
When the reference count of the serial port class goes to zero (the object
reference goes out of scope) the port must be closed immediately. Otherwise,
if the user tries to open the port for another session it will fail because
the port is still open from the previous session.
There are NO reference counts in VB.NET! the GC does not use Reference
Counts it actually checks all variables to see if one of them currently
reference the object. For a reasonable complete explanation of how this
works see:

http://msdn.microsoft.com/msdnmag/issues/1100/gci/
http://msdn.microsoft.com/msdnmag/issues/1200/GCI2/

Largely because there is no reference counts, VB.NET cannot know when to
clean up an object! The GC itself needs to do it, at its leisure.
I suppose what I want is a method on the serial class that I can guarantee
will be called when the object reference goes out of scope. Then I can
recover in the event that the caller does not call Dispose.
As I've tried to state There is no method! Or more appropriately the
Finalize/Dispose pattern is the method! ;-)
As far as closing the application goes, the user clicks the Close button,
top right. In this case, because Finalize is not called, the serial class
keeps the application and debugger alive. This is because it starts a second
thread to read characters from the port asynchronously, which never gets
shut down.
Ah! there's the rub!!! ;-)

Does this second thread reference your serial class also? I would expect
that it needs to reference your serial class as its reading from it, hence
there is a "live" reference to your object, ergo the GC cannot collect it.
If the GC cannot collect it, then the Finalize method cannot be called!

You need to "notify" the second thread that it is time to finish, the
"preferred" method is to use an AutoResetEvent or ManualResetEvent or other
"flag" that the main thread can set that the background thread can check. I
normally embed the serialport, ResetEvent, and Thread in a class of its own
that has methods that each thread uses to "communicate" with the other
thread.

Alternatively when you create the Background Thread, do you set the
Thread.IsBackground property, so that it knows it should be aborted when the
main thread exists?

A third alternative, would be to handle the Application.ThreadExit or
Application.AppliationExit in your serial class so it knows when your "main
thread" exited, allowing it to "give up"

I'm sure there are a couple of other possibilities ;-)

Hope this helps
Jay

Charles Law said:
Hi Jay

Perhaps OO is the wrong expression, but I am referring to the concept of
encapsulation. To require Dispose to be called by the user of a service
implies that they know something about the internal operation of the
service, i.e. that it has unmanaged resources that need to be released.

Although you say that if they don't call Dispose the Finalize method will
take care of it, it is also the case that you cannot guarantee when the
Finalize method will be called (if at all, in the case of exiting the
program).

The situation I have is a main form that creates a class. This class opens a
serial port. It may open a second serial port, and may also open one and
close another.

When the reference count of the serial port class goes to zero (the object
reference goes out of scope) the port must be closed immediately. Otherwise,
if the user tries to open the port for another session it will fail because
the port is still open from the previous session.

I have read the articles you pointed to, but they basically confirm the
non-deterministic nature of the Finalize method.

I can see how the Dispose method allows the developer to force an object to
free its handles etc. but failure to do so would cause the serial class to
misbehave, which I want to avoid (as an implementor of the serial class).

I hope that all makes sense.

I suppose what I want is a method on the serial class that I can guarantee
will be called when the object reference goes out of scope. Then I can
recover in the event that the caller does not call Dispose.

As far as closing the application goes, the user clicks the Close button,
top right. In this case, because Finalize is not called, the serial class
keeps the application and debugger alive. This is because it starts a second
thread to read characters from the port asynchronously, which never gets
shut down.

Is there anything I can do about this, as the implementor of the serial
class?

Charles
<<snip>>
 
C

Charles Law

Jay

Thanks for a thorough treatment of the problem. You have given me several
ideas for ways out of the dilemma, and I understand the reasons a lot better
now.

Many thanks again.

Charles
 
A

Armin Zingler

Charles Law said:
I don't know whether I am surprised or not, but this seems quite an
omission from VB.NET. I can't see the logic for not providing a
destructor in VB.NET.

Because there is (fortunatelly) no reference counter. ;-)
 
A

Armin Zingler

Charles Law said:
Perhaps OO is the wrong expression, but I am referring to the concept
of encapsulation. To require Dispose to be called by the user of a
service implies that they know something about the internal operation
of the service, i.e. that it has unmanaged resources that need to be
released.
[...]

In addition to Jay, my 2 Euro-c in my own words:
As GC belongs to the basics of .NET development, every programmer must be
aware of it. Consequently we also must be aware of the fact that objects are
not destroyed immediatelly. In addition, every programmer knows that objects
occupy resources, including memory and native resources.

In other words, the fact that an object occupies resources is nothing that
has to be encapsulated because it is basic knowledge. I'd call it a feature
when giving the client objects the possibility to free resources via the
Dispose method.

Still, I'm not sure whether Finalize should be called when the app quits. As
my NotifyIcon example shows, I think it should be called. I thought a simple
basic rule is: When an object is destroyed, Finalize is called. This is not
true. What if I wanted to log the lifetime, of an object and I do it in the
ctor and in Finalize? As I can't rely on Finalize being called.....

I can see how the Dispose method allows the developer to force an
object to free its handles etc. but failure to do so would cause the
serial class to misbehave, which I want to avoid (as an implementor
of the serial class).

Failures cause such things. ;-)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top