无法访问已处置的对象错误

时间:2013-08-02 16:33:23

标签: c# winforms

我收到错误消息无法访问已处置的对象。 对象名称:'ApplicationProperties'。当我在关闭它后尝试重新打开表单时。我注意到这是来自退出表单,退出是“Disposing”,所以我将以下代码放在我的所有接受按钮中,并取消按钮(任何关闭表单的按钮)

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

此代码只是隐藏表单。 未关闭表单。

所以我的问题是,当我单击表单上的“x”按钮,然后尝试重新打开表单时仍然会收到错误消息。我尝试了几种不同的方法来修改表单的现有功能,例如:

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

但这给我带来了好运。我想知道是否有人知道如何解决这个问题。这是在我的取消和接受按钮内为我工作的代码。关闭表单的所有按钮都是一样的。

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

我已经在form1的类顶部声明了实例,并在form1中有一个打开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.
 }

在我使用第二个表单上的“x”按钮关闭程序后,由于ApplicationPropertiesWindow.Show();

处的错误消息,我无法再次访问form2

在form2中我有以下代码:

public partial class ApplicationProperties : Form
{
    //Creates and sets the instance MainBoxWindow.
    public MainBox MainBoxWindow { get; set; }

4 个答案:

答案 0 :(得分:6)

FormClosing事件中尝试此操作:

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

因为现在它仍在关闭表单,因此仍然会导致错误。

答案 1 :(得分:4)

  

我用第二张表格上的'x'按钮关闭程序后   由于触发错误消息,无法再次访问form2   ApplicationPropertiesWindow.Show();

当表单关闭(Form.Close)时,表单本身及其所有相关资源都将被释放。如文档中所述,此自动处理只有两个例外:

  1. 表单是MDI应用程序的一部分,可见。
  2. 使用ShowDialog(而不是Show)将表单显示为模式对话框。它以这种方式设计,以便您可以在用户关闭对话框后访问该对话框的属性(例如,检索用户输入)。
  3. 在这两种特殊情况下,您都有责任手动调用表单的Dispose方法。第二种情况是迄今为止最常见的(没有人真正使用MDI范例),并且可以使用using语句轻松处理:

    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
    

    在您的情况下,通常情况下,对Close方法的调用是关闭并销毁表单。您已经知道您无法访问已处置的对象(因为它不再存在!),因此当您尝试显示它时,这就是您获得异常的原因。为了在关闭后再次显示表单,您需要创建表单类的新实例:

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

    这是最好的方法。表单的新实例将与您关闭的实例相同,因为它是从同一个类创建的。您最好开始考虑面向对象的术语,尽可能避免使用基于单件的设计。屏幕上显示的每个表单都是一个新的独立对象。一旦该对象被关闭并销毁,您就不能再使用它了。如果要再次使用它,则需要创建一个新对象并显示它。

    Hide方法更像是一种黑客攻击,只有当你想暂时隐藏表单的当前实例同时仍保留其状态(例如,其成员属性的值,其控制状态等)时才有用。 )。这仅适用于永远不会被销毁的单件对象,必须仔细设计和维护。这也意味着这个表单对象一直消耗资源,无论是否被使用,都是浪费。

    如果必须执行此操作,则需要跟踪导致表单实例处理的原因。在没有看到所有代码的情况下,我很难做任何事情,但要猜测问题可能在哪里。这可能与您使用AcceptButton和/或CancelButton属性有关。无论哪种方式,最好和最干净的解决方案是覆盖OnFormClosing方法并防止您的表单被关闭。你会隐藏它:

    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
    }    
    

    这样做的好处是,您只需将代码放在一个位置,这是负责类的本地代码,而不是暴露给外部代码并分散在整个应用程序中。当然,它还可以防止表单被您无法控制的框架代码关闭。

    我不知道你为什么要将Parent属性设置为null。顶级窗口(所有表单都是这样)可以永远不会有父级。只有子窗口(例如控件)才有父母。 可以拥有所有者,但不一定如此。这取决于在调用Show方法时是否将所有者窗口作为参数传递。

答案 2 :(得分:3)

首先删除this.Parent = null bcose隐藏表单

时不需要这样做

现在,当您隐藏表单时,如果您仍想在静态var中访问此表单存储表单。当对象不再使用时,Bcous垃圾收集器处理它并且它将不再可用。

答案 3 :(得分:3)

问题,至少可能是其中的一部分,看起来像是阶级相互依赖。

初始化ApplicationProperties实例时,您正在创建对MainBox对象的引用,但在MainBox类的定义中,您正在创建新的ApplicationsProperties类。 1}}对象,它引用了MainBox ....我甚至让自己感到困惑。 MainBox是您的父表单,即启动应用程序时加载的表单吗?

如果MainBox中的某些内容在ApplicationProperites类中设置了对它的引用,那么ApplicationProperties中的某些内容会被摧毁...当你单击“X”时会被处置掉,我不会感到惊讶。再次,这是一个有根据的猜测;我不确定是不是这个原因,但即使代码不是错误本身,它对我来说也很古怪。

如果您希望ApplicationProperties窗口永远持续并简化操作,只需在应用程序持续时间的任何形式的开头初始化它的静态实例,并显示/隐藏它类似你最初的尝试。如果你想要高效和基础,只要你需要让用户修改它,就构造和处理{{1}},但是杀死循环依赖。