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

时间:2010-04-19 21:57:04

标签: c# exception forms objectdisposedexception

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

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


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次会导致异常,或者更确切地说,为什么我的表格会被处理?

我怀疑垃圾收集器感到困惑,因为它在运行了好几个小时之后更频繁地发生轻微

2 个答案:

答案 0 :(得分:3)

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

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

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

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

(请注意,如果您反对MDI,您可以使用表单Owners基本上做同样的事情。)

// 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();

答案 1 :(得分:2)

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