3

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

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


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 功能,“关闭”和“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 的时间会导致异常,或者更确切地说,为什么我的表单会被处理?

我怀疑垃圾收集器被搞糊涂了,因为它在运行了几个小时后发生的频率稍微高了一点。

4

2 回答 2

3

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

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

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

相反,您可能应该考虑使用 MDI(多文档界面)父表单,而您的“子表单”称为 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();
于 2010-04-19T22:13:27.797 回答
2
try 
{
    // Validate form not disposed before using. Initialize as needed. 
    if  (xDataForm == null || xDataForm.IsDisposed)
    {
        xDataForm = new MyDataFormName();
    }
    xDataForm.Show(); 
    xDataForm.Activate(); 
} 
于 2010-04-20T01:03:10.680 回答