简体   繁体   中英

Why does my destructor never run?

I have a blank Winform with a destructor method

public partial class Form1 : Form
{
    public Form1()
    {
        System.Diagnostics.Trace.WriteLine("Form1.Initialize " + this.GetHashCode().ToString());
        InitializeComponent();
    }
    ~Form1()
    {
        System.Diagnostics.Trace.WriteLine("Form1.Dispose " + this.GetHashCode().ToString());
    }
}

When the form is destroyed, I want it to write to the output window:

(Form1 opened)
Form1.Initialize 41149443
(Form1 closed)

MSDN suggests 3 ways in implementing destructor:

However, none of these ways write "Form1.Dispose 41149443" to the output Window. Therefore, I am not able to tell whether the form has been destroyed or not. Suggestions ?

Should I give up hope on achieving this due to uncertainty of garbage collector?

Is there another way to know whether Form1 has been garbage collected ?

Only one of the three ways to implement a destructor that you list actually involves a destructor, and that's ~Destructor() .

If you implement IDisposable , and dispose of your object, then the code in Dispose will run, but there's no reason to think that your destructor will.

I think you chasing the impossible here. Destructors run as and when the garbage collector so decrees. It's not something that you have any control over. The GC is well within its rights to form the opinion that running destructors simply wastes time, and if there is plenty of memory it will form that opinion.

If you need predictable disposal, finalization etc., then use IDisposable .

Unless you are studying garbage collection, a destructor is not the place for your tracing. You should look at Dispose (which is overridable in Form). This occurs after the unmanaged resource (like your window handle) has been released.

protected override void Dispose(bool disposing)
{
   System.Diagnostics.Trace.WriteLine(
      "Form1.Dispose " + (disposing ? "disposing " : "")
      + this.GetHashCode().ToString());
   base.Dispose (disposing);
}

If you want to see if a form/control has been disposed, use the Control.IsDisposed property.

Edit: Because of GC.SuppressFinalize , your Finalize method (destructor syntax in C#) will never execute if Dispose is called explicitly (or by the framework).

For more information, see Implementing a Dispose Method .

Add a FormClosed event to the designer.

ie:

this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(Form1_FormClosed);

Then create the appropriate function to handle the event.

Yes, you should probably give up on the idea of a destructor, because they're non-deterministic by nature. I'm not sure why you need to have the form disposed as opposed to just closed, but simply closing it should be enough in most cases.

You could use IDisposable but that depends on why you need the form to be garbage collected. If you need to re-use it, just create another instance.

The Form gets garbage collected when no references exist and the garbage collector happens to run. You can force the garbage collector by calling GC.Collect(). You should not reference any other object within a Finalizer (aka destructor) because the object might have been garbage collected already.

You can use memory analyzer tools to find out whether your object is garbage collected or not, if you really need to.

You also have to keep in mind that the finalizer is called from a thread other than the main thread.

EDIT: If your problem is just that you don't see the trace output, you might have to turn autoflush on

<configuration>
  <system.diagnostics>
    <trace autoflush="true" />
  </system.diagnostics>
</configuration>

EDIT 2: There might be an external reference to your form, such as a registered event handler. I would suggest that you add a button in an administration area of your application which executes the following code:

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

Like this the garbage collector must run and should destroy your form (set a breakpoint into the finalizer). If not, you have some reference to the object which has to be destroyed.

You could try wrapping your form in a WeakReference object then check its IsAlive property to determine if it has been garbage collected. But, yes...as per the other answers you may be better off leaving it and trusting the GC to do its job!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM