C# 无法访问已处理的对象错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18021972/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Cannot access a disposed object error
提问by Chase Ernst
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:
所以我的问题是,当我单击表单上的“x”按钮,然后尝试重新打开表单时,我仍然收到错误消息。我尝试了几种不同的方法来修改表单的退出功能,例如:
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.
我已经在 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.
}
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();
在我使用第二个表单上的“x”按钮关闭程序后,我无法再次访问 form2,因为错误消息在 ApplicationPropertiesWindow.Show();
Inside form2 I have the following code:
在 form2 中,我有以下代码:
public partial class ApplicationProperties : Form
{
//Creates and sets the instance MainBoxWindow.
public MainBox MainBoxWindow { get; set; }
采纳答案by Hanlet Esca?o
Try this in your FormClosing
event:
在你的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
}
cause right now it is still closing the form, thus still causing the error.
因为现在它仍在关闭表单,因此仍然导致错误。
回答by sourabh devpura
First remove this.Parent=null bcose this is not required when you hiding the Form
首先删除 this.Parent=null 因为隐藏表单时不需要
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 .
现在,当您隐藏 Form 并且您仍然想访问这个 Form 存储表单时,静态 var 。Bcous 当对象不再使用垃圾收集器处理它并且它将不再可用。
回答by B L
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?
当您初始化一个ApplicationProperties
实例时,您正在创建对一个MainBox
对象的引用,但在MainBox
类的定义中,您正在创建一个新ApplicationsProperties
对象,该对象引用了MainBox
.... 我什至让自己感到困惑。是MainBox
你的父窗体,在一个负载,当你启动应用程序?
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 wrongper se, it looks quirky to me.
MainBox
如果您在ApplicationProperites
类中设置了对它的引用,如果其中的某些内容被无意中破坏,我不会感到惊讶……当您单击“X”时正在处理。同样,这是一个有根据的猜测;我不确定这是否是原因,但即使代码本身没有错误,对我来说它看起来也很古怪。
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.
如果你希望你的ApplicationProperties
窗口永远持续下去并简化事情,只需在任何形式的开头初始化它的一个静态实例,它将持续你的应用程序的持续时间,并像你最初尝试的那样显示/隐藏它。如果你想高效和根本,ApplicationProperties
只要你需要让用户修改它,就可以构造和处置它,但要杀死循环依赖。
回答by Cody Gray
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();
在我使用第二个表单上的“x”按钮关闭程序后,我无法再次访问 form2,因为错误消息在
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:
当表单关闭 ( Form.Close
) 时,表单本身及其所有相关资源都将被释放。这种自动处理只有两个例外,如文档中所述:
- The form is part of a MDI application and notvisible.
- The form was displayed as a modal dialog using
ShowDialog
(as opposed toShow
). 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.
- 该表单是 MDI 应用程序的一部分,不可见。
- 该表单使用
ShowDialog
(而不是Show
)显示为模态对话框。它以这种方式设计,以便您可以在用户关闭对话框后访问对话框的属性(例如,检索用户输入)。
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:
在这两种特殊情况下,您负责手动调用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
In your case, as is typical, the call to the Close
method is closing and destroyingthe 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:
在您的情况下,通常情况下,对该Close
方法的调用正在关闭和销毁表单。您已经知道您无法访问已处置的对象(因为它不再存在!),所以这就是您在尝试显示它时收到异常的原因。为了在关闭后再次显示表单,您需要创建表单类的新实例:
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.
该Hide
方法更像是一种技巧,仅当您想暂时隐藏表单的当前实例同时仍保留其状态(例如,其成员属性的值、其控件状态等)时才有用。这仅适用于永远不会被销毁的单例对象,并且必须仔细设计和维护。这也意味着这个表单对象一直在消耗资源,不管它是否被使用,都是一种浪费。
If you mustdo 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:
如果您必须这样做,您需要追踪导致您的表单实例被处理的原因。没有看到您的所有代码,我很难做任何事情,只能猜测问题可能出在哪里。这可能与您对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
}
The advantage of this is that you only have to have the code in oneplace, 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 canhave an owner, but it will not necessarily. It depends on whether you pass an owner window as an argument when calling the Show
method.
我不知道你为什么将Parent
属性设置为null
. 顶级窗口(所有表单都是如此)永远不会有父窗口。只有子窗口(例如控件)有父窗口。它可以有一个所有者,但不一定。这取决于您在调用该Show
方法时是否将所有者窗口作为参数传递。