Domanda

I'm having destructor issues. Here is code that repros the problem:

class DPDemo : DependencyObject
{
    public DPDemo()
    {

    }

    ~DPDemo()
    {
        Console.WriteLine(this.Test);   // Cross-thread access
    }

    public int Test
    {
        get { return (int)GetValue(TestProperty); }
        set { SetValue(TestProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Test.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty TestProperty =
        DependencyProperty.Register("Test", typeof(int), typeof(DPDemo), new PropertyMetadata(0));
}

When the destructor runs, I get an InvalidOperationException on the line get {SetValue.... Is there a recommended way to read dependecy properties from the destructor, or another thread in general?

È stato utile?

Soluzione

The ~ClassName() function is not a destructor, it is a finalizer. It serves a very different job than a C++ destructor. Once you are in the finalizer stage of a objects life-cycle you can not reliably call on other objects the class contains as they may have been already destroyed before your finalizer was called. The only thing you should be doing in a finalizer is releasing unmanaged resources or calling the Dispose(false) function in a correctly implemented dispose pattern.

If you need a "destructor" you need to implement the IDisposable pattern correctly to get your code to behave in a proper manner.

Please also see this question and answer for more tips on writing a good IDisposable pattern and it also helps explain on why you are getting errors (see the part where he starts talking about the finalizer).


To answer your comment: No it does not. C# has no method of reliably calling a function at the end of life of a object automatically (IDisposable classes + the using statement replaces it). If your object implements IDisposable it is the callers resposibility to dispose the object.

In your WPF app's OnClose method you will need to call your class's Save functionality. You don't really need your class to be IDisposable at all.

//Inside the codebehind of your WPF form
public partial class MyWindow: Window
{
    //(Snip)

    protected override void OnClosed(EventArgs e) //You may need to use OnClosing insetad of OnClose, check the documentation to see which is more appropriate for you.
    {
        _DPDemoInstance.Save(); //Put the code that was in your ~DPDemo() function in this save function.
                                //You could also make the class disposeable and call "Dispose()" instead.
    }
}

Altri suggerimenti

I recommend use the IDisposable interface, and operate the DependencyObject in the Dispose method.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top