繁体   English   中英

当.Show()表示不应该处理的表单时,ObjectDisposedException

[英]ObjectDisposedException when .Show()'ing a form that shouldn't be disposed

我已经检查了一些其他问题,显然最好的解决方案是首先防止导致此问题的行为,但问题是非常间歇性的,并且非常不可重现。

我基本上有一个主表单,子表单。 从主窗体的菜单和/或按钮显示子窗体,如下所示:


private void myToolStripMenuItem_Click(object sender, EventArgs e)
{
    try
    {
        xDataForm.Show();
        xDataForm.Activate();
    }
    catch (ObjectDisposedException)
    {
        MessageBox.Show("ERROR 10103");
        ErrorLogging newLogger = new ErrorLogging("10103");
        Thread errorThread = new Thread(ErrorLogging.writeErrorToLog);
        errorThread.Start();
    }
}

并且子表单实际上是主要形式(无论好坏。我实际上想改变它,但这将是相当长的时间):


public partial class FormMainScreen : Form
{
    Form xDataForm = new xData();
    ...(lots more here)

    public FormMainScreen(int pCount, string pName)
 {
        InitializeComponent();
        ...
 }
    ...
}

子表单的Dispose函数被修改,以便'close'和'X'按钮实际隐藏表单,所以我们不必每次都重新创建它。 当主屏幕关闭时,它将“标志”设置为2,因此其他形式知道它实际上可以关闭;


protected override void Dispose(bool disposing)
{
    if (FormMainScreen.isExiting == 2) 
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }
    else
    {
        if (xData.ActiveForm != null)
        {
            xData.ActiveForm.Hide();
        }
    }
}

所以,问题是,为什么这种方法会一遍又一遍地完美无缺,但是,从字面上讲,大约每1/1000个时间都会引起异常,或者更确切地说,为什么我的表格会被处理?

more frequently after it has been running for many hours. 我有一个怀疑,垃圾收集器是感到困惑,因为它会出现更频繁它已经运行了几个小时后。

没有冒犯,但这似乎是很久以前解决的问题的一个非常复杂的解决方案。

除了处理其他一次性用品之外,你不应该在Dispose()方法中做任何事情(即使只有在处置标志为真时才这样做。)所以我不会修改设计者为你生成的方法。

因此,关于为什么会发生这种情况的问题的直接答案几乎肯定与垃圾收集器调用Dispose方法的时间有关。

相反,您应该考虑使用MDI( 多文档界面 )父表单,而您的“子表单”称为MDI子表单。 然后,您可以像这样处理子项中的FormClosing事件。

(请注意,如果您反对MDI,则可以使用表单所有者执行基本相同的操作。)

// MDI child
private void Form_FormClosing(object sender, FormClosingEventArgs e) {
    if (e.CloseReason == CloseReason.UserClosing) {
        e.Cancel = true;
        Hide();
    }
}

当表单因各种原因关闭时,例如关闭代码,父表单正在关闭,Windows正在关闭等等,那么结束将不会被取消。 仅当窗口因为用户直接关闭子窗体而关闭时才会隐藏它。

要在MDI父级内部显示MDI子级,您可以执行以下操作:

MyParentForm parentForm = new MyParentForm();
parentForm.IsMdiContainer = true;
parentForm.Show();

MyChildForm childForm = new MyChildForm();
childForm.MdiParent = parentForm;
childForm.Show();
try 
{
    // Validate form not disposed before using. Initialize as needed. 
    if  (xDataForm == null || xDataForm.IsDisposed)
    {
        xDataForm = new MyDataFormName();
    }
    xDataForm.Show(); 
    xDataForm.Activate(); 
} 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM