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

Cha*_*nst 10 c# winforms

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

 this.Hide(); 
 this.Parent = null;
Run Code Online (Sandbox Code Playgroud)

这段代码只是隐藏了表单.没有关闭表格.

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

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

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

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

我已经在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.
 }
Run Code Online (Sandbox Code Playgroud)

在我使用第二个表单上的"x"按钮关闭程序后,由于发生错误消息,我无法再次访问form2 ApplicationPropertiesWindow.Show();

在form2中我有以下代码:

public partial class ApplicationProperties : Form
{
    //Creates and sets the instance MainBoxWindow.
    public MainBox MainBoxWindow { get; set; }
Run Code Online (Sandbox Code Playgroud)

Han*_*año 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
   }
Run Code Online (Sandbox Code Playgroud)

因为现在它仍在关闭表格,因此仍然导致错误.


Cod*_*ray 5

在我使用第二个表单上的“x”按钮关闭程序后,我无法再次访问 form2,因为错误消息在 ApplicationPropertiesWindow.Show();

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

  1. 该表单是 MDI 应用程序的一部分,可见。
  2. 该表单使用ShowDialog(而不是Show)显示为模态对话框。它以这种方式设计,以便您可以在用户关闭对话框后访问对话框的属性(例如,检索用户输入)。

在这两种特殊情况下,您负责手动调用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
Run Code Online (Sandbox Code Playgroud)

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

MyForm frm = new MyForm();
frm.Show();
// ...
frm.Close();
Run Code Online (Sandbox Code Playgroud)

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

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
}    
Run Code Online (Sandbox Code Playgroud)

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

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