Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot access a disposed object error

Tags:

c#

winforms

I am getting the error message Cannot access a disposed object. Object name: 'ApplicationProperties'. when I tryo to re-open a form after closing it. I have noticed this is from exiting forms, and exiting is "Disposing" of them, so I have put the following code in all of my accept buttons, and cancel buttons (any button that closes a form).

 this.Hide(); 
 this.Parent = null;

This code is just hiding the form. Not closing the form.

So what my problem is, is that when I click the 'x' button on the form, then try to re-open the form I still get the error message. I have tried a couple differnet ways to modify the exiting funciton of the form such as:

    private void ApplicationProperties_FormClosing(object sender, FormClosingEventArgs e)
    {
        //Hiding the window, because closing it makes the window unaccessible.
        this.Hide();
        this.Parent = null;
    }

But this has brought me no luck. I was wondering if anyone knows how to solve this problem. Here is the code that is working for me inside my cancel and accept buttons. It is the same for all of my buttons that close forms.

    private void OptionsCancelbtn_Click(object sender, EventArgs e)
    {
        //Hiding the window, because closing it makes the window unaccessible.
        this.Hide();
        this.Parent = null;
    }

I have declared the instance at the top of my class on form1, and have a button inside form1 that opens form2.

public partial class MainBox : Form
{
    //Making a name for the ApplicationProperties form. It can be opened when called.
    ApplicationProperties ApplicationPropertiesWindow = new ApplicationProperties();
    private void ApplicationPropertiesbtn_Click(object sender, EventArgs e)
    {
        //Show the properties window.
        ApplicationPropertiesWindow.Show();
    }//End ApplicationProperties button.
 }

After I close the program with the 'x' button on the second form I cannot access form2 again because of the error message firing at ApplicationPropertiesWindow.Show();

Inside form2 I have the following code:

public partial class ApplicationProperties : Form
{
    //Creates and sets the instance MainBoxWindow.
    public MainBox MainBoxWindow { get; set; }
like image 267
Chase Ernst Avatar asked Aug 02 '13 16:08

Chase Ernst


People also ask

What is System ObjectDisposedException?

An ObjectDisposedException is thrown when you try to access a member of an object that implements the IDisposable interface or IAsyncDisposable interface, and that object has been disposed.

How check object is disposed or not in C#?

While the framework itself doesn't give any guarantees, the documentation for IDisposable says this: "If an object's Dispose method is called more than once, the object must ignore all calls after the first one. The object must not throw an exception if its Dispose method is called multiple times.


3 Answers

After I close the program with the 'x' button on the second form I cannot access form2 again because of the error message firing at ApplicationPropertiesWindow.Show();

When a form is closed (Form.Close), the form itself and all of its associated resources are freed. There are only two exceptions to this automatic disposal, as noted in the documentation:

  1. The form is part of a MDI application and not visible.
  2. The form was displayed as a modal dialog using ShowDialog (as opposed to Show). It is designed this way so that you can access properties of the dialog (e.g. to retrieve user input) after the user has closed it.

In both of these special cases, you are responsible for manually calling the Dispose method of the form. The second case is by far the most common (no one really uses the MDI paradigm anymore), and is handled easily with a using statement:

using (MyDialogBox dlg = new MyDialogBox())
{
    DialogResult result = dlg.ShowModal(this);
    if (result == DialogResult.Yes)
    {
        // access members of "dlg", and
        // do whatever the user asked
    }
}  // the Dispose method is automatically called here

In your case, as is typical, the call to the Close method is closing and destroying the form. You already know that you cannot access a disposed object (because it no longer exists!), so that's why you're getting the exception when you try to show it. In order to show the form again after it has been closed, you need to create a new instance of the form class:

MyForm frm = new MyForm();
frm.Show();
// ...
frm.Close();

This is really the best method. A new instance of the form will be identical to the one you're closing because it was created from the same class. You would do best to start thinking in object-oriented terms and avoid singleton-based designs whenever possible. Each form that shows up on the screen is a new, independent object. Once that object is closed and destroyed, you cannot use it any longer. If you want to use it again, you need to create a new object and display it.

The Hide method is more of a hack, useful only when you want to temporarily hide the current instance of a form while still retaining its state (e.g., the values of its member properties, its control states, etc.). This works only with singleton objects that will never be destroyed, and must be carefully designed and maintained. It also means that this form object consumes resources all the time, whether it is being used or not, which is wasteful.

If you must do this, you'll need to track down what is causing your form instance to be disposed. Without seeing all of your code, it's hard for me to do anything but guess at where the problem might be. It is likely related to your use of the AcceptButton and/or CancelButton properties. Either way, the best and cleanest solution is to override the OnFormClosing method and prevent your form from ever being closed. You'll hide it instead:

public class MyForm : Form
{
    protected virtual void OnFormClosing(FormClosingEventArgs e)
    {
        // Prevent the form from closing.
        e.Cancel = true;

        // Hide it instead.
        this.Hide();
    }

    // ...other code in your form class
}    

The advantage of this is that you only have to have the code in one place, local to the responsible class, rather than exposed to external code and scattered throughout your application. And of course, it also prevents the form from ever being closed by framework code outside of your control.

I have no idea why you're setting the Parent property to null. A top-level window (which is what all forms are) can never have a parent. Only child windows (e.g. controls) have parents. It can have an owner, but it will not necessarily. It depends on whether you pass an owner window as an argument when calling the Show method.

like image 152
Cody Gray Avatar answered Oct 18 '22 15:10

Cody Gray


First remove this.Parent=null bcose this is not required when you hiding the Form

Now when you hiding the Form and if you still want to access this Form store form in static var . Bcous when object is no longer in use garbage collector dispose it and it will no longer available .

like image 33
sourabh devpura Avatar answered Oct 18 '22 16:10

sourabh devpura


The problem, at least perhaps part of it, looks like a bit of class interdependence.

When you initialize an ApplicationProperties instance, you're creating a reference to a MainBox object, but in the definition of the MainBox class, you're creating a new ApplicationsProperties object, which references a MainBox.... I'm even confusing myself. Is MainBox your parent form, the one that loads when you start the application?

I wouldn't be surprised if some stuff in MainBox is getting destroyed inadvertently if you set a reference to it in the ApplicationProperites class... which is disposing when you click "X". Again, this is an educated guess; I'm not sure if that's the reason but even if the code isn't wrong per se, it looks quirky to me.

If you want your ApplicationProperties window to last forever and to simplify things, just initialize a static instance of it at the beginning of whatever form is going to persist the duration of your application, and show/hide it similar to what you were attempting originally. If you want to be efficient and fundamental, construct and dispose ApplicationProperties whenever you need to let the user modify it, but kill the circular dependency.

like image 31
B L Avatar answered Oct 18 '22 16:10

B L