【问题标题】:Even though form3 is created from form2, why it is not disposed on form2 close?即使 form3 是从 form2 创建的,为什么它没有在 form2 关闭?
【发布时间】:2009-12-08 07:01:43
【问题描述】:

我需要您的帮助来澄清表单是否完全像对象一样工作?

如果我从另一个对象 obj1 创建一个对象 obj2。 obj2 将在 obj1 dispose 上进行处理。

但表单并非如此。 查看下面给出的案例和伪代码。

我有三种形式;表格 1、表格 2 和表格 2。

form1 是启动表单。 form1 将创建 &s form2 和 from2 如何使用每个表单中的按钮创建和显示 form3。

如果我关闭form2,在打开所有3个表格后,我可以在form1和form3中工作。

我的问题是即使 form3 是从 form2 创建的,为什么它没有在 form2 close 上处理?

Form1


Public Class Form1
Private Sub cmdOpenForm2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdOpenForm2.Click
  Dim frm As New Form2
  With frm
   ''/.MdiParent = frmMain
   .Show()
   .BringToFront()
  End With
End Sub

 Private Sub Form1_Disposed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Disposed
  ''//frmMain.tsStatus.Text = "Form1 disposed"
 End Sub
End Class

Form2


Public Class Form2
 Private Sub cmdRandomColor_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdRandomColor.Click
  Randomize()
  Label1.ForeColor = Color.FromArgb(Rnd() * 255, Rnd() * 255, Rnd() * 255, Rnd() * 255)
 End Sub

 Private Sub Form2_Disposed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Disposed
  frmMain.tsStatus.Text = "Form2 disposed"
 End Sub

 Private Sub cmdOpenForm3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdOpenForm3.Click
  Dim frm As New Form3
  With frm
   ''//.MdiParent = frmMain
   .Show()
   .BringToFront()
  End With
 End Sub
 End Class

Form3


Public Class Form3
 Private Sub cmdRandomColor_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdRandomColor.Click
  Randomize()
  Label1.ForeColor = Color.FromArgb(Rnd() * 255, Rnd() * 255, Rnd() * 255, Rnd() * 255)
 End Sub

 Private Sub Form3_Disposed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Disposed
  frmMain.tsStatus.Text = "Form3 disposed"
 End Sub
End Class

任何帮助将不胜感激。

编辑 谢谢大家的解决方案

抱歉,我不是在寻找如何在 form2 关闭时处理 form3 的解决方案

我的兴趣是背后发生的事情......从2创建的form3实例是否有可能获得GC收集并且我得到内存错误。

因为我在实际应用程序中遇到保护内存访问异常,该应用程序设计不正确,并且现在太大而无法重构。

我的问题是 form3 实例在哪里创建?它是在 Form2 实例中还是在其他地方。 因为我可以在 form2 处理后访问 form3 实例。我怀疑它是在其他地方创建的

【问题讨论】:

    标签: winforms


    【解决方案1】:

    在与您自己创建的新表单相关的表单上的 Dispose 调用中不会自动发生任何事情。

    如果您希望表单自动处理它创建的表单,您必须自己添加代码来执行此操作。要么找到设计者添加的 .Dispose 方法,并在那里添加,要么在表单上实现 FormClosed 事件。

    form2 “创建” form1 不会在两者之间建立任何关系。

    【讨论】:

    • 我的问题是为什么?由于 form3 实例是从 form2 实例创建的,为什么要在 form2 上处理。它正在触发 form3 dispose?
    【解决方案2】:

    可选择自动处理。该表单必须是“拥有”表单。最简单的方法是使用 Form.Show(owner) 重载:

    private void button1_Click(object sender, EventArgs e) {
      new Form3().Show(this);
    }
    

    或者您可以在之后使用 Form.AddOwnedForm() 方法执行此操作。请注意,这有副作用,拥有的表单始终显示在所有者面前。它将与所有者一起最小化和恢复。如果您不希望这样,您可以明确跟踪表单的生命周期并自行处理:

    private Form3 mForm3;
    
    private void button1_Click(object sender, EventArgs e) {
      if (mForm3 == null) {
        mForm3 = new Form3();
        mForm3.FormClosed += (s, ea) => mForm3 = null;
        mForm3.Show();
      }
      else {
        mForm3.WindowState = FormWindowState.Normal;
        mForm3.Focus();
      }
    }
    
    protected override void OnFormClosed(FormClosedEventArgs e) {
      if (mForm3 != null) mForm3.Dispose();
    }
    

    【讨论】:

      【解决方案3】:

      框架仍然持有您的表单对象,直到它被关闭。您可以使用My.Application.OpenForms 获取对它的引用。

      【讨论】:

      • 您能解释一下原因吗?是这样吗?为什么form3实例对象在创建者对象,form2实例,dispose的时候被dispose?
      • 当不再存在对表单对象的引用时,将释放表单对象(除非您明确调用 .Dispose on is)。只要窗体正在由 Windows 使用,框架就会引用它。所以只要你能看到表格,其实是有引用的。您在代码中创建表单的位置根本不重要。
      【解决方案4】:

      如果我从另一个对象 obj1 创建一个对象 obj2。 obj2 将在 obj1 dispose 上进行处理。

      不一定。如果其他对象,比如obj3 引用了obj2,那么即使在obj1 被垃圾回收之后,obj2 也会继续存在。

      在这种情况下,窗口管理器引用了form3,因此即使form2 存在,它也不会被垃圾回收。

      【讨论】:

      • 嗨,匿名,但是我从 Form2 创建了 form3,它保存了该表单的实例,frm。所以我的问题是为什么表单的实例对象没有在 Form2 上关闭。如果已处置;如果没有,form3 如何仍然能够执行事件,实例对象存储在哪里以及我如何访问该实例。
      【解决方案5】:

      您必须使用以 Win32-Window-Handle 作为参数的 Form-Constructor。然后,您可以将 form2 的引用传递给 form3,它会按预期工作。

      Private Sub cmdOpenForm2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdOpenForm2.Click
        Dim frm As New Form2(Me)
        With frm
         .Show()
         .BringToFront()
        End With
      End Sub
      

      【讨论】:

        【解决方案6】:

        如果您将表单变量更改为实例变量,并将其包含在 Show 方法中,它将起作用

        Form1 代码

        public partial class Form1 : Form
            {
                Form2 f;
                public Form1()
                {
                    InitializeComponent();
                }
        
                private void button1_Click(object sender, EventArgs e)
                {
                    f = new Form2();
                    f.Show(this);
                }
        
                private void button2_Click(object sender, EventArgs e)
                {
                    f.Close();
                    f = null;
                }
            }
        

        Form2 代码

        public partial class Form2 : Form
            {
                Form3 f;
                public Form2()
                {
                    InitializeComponent();
                }
        
                private void button1_Click(object sender, EventArgs e)
                {
                    f = new Form3();
                    f.Show(this);
                }
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-01-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多