如果不用MDI来实现一个主窗体打开多个子窗体时,

从一个窗体(主窗体)打开一个(only one) 另外一个的窗体(子窗体)的实现

 

父窗体:MainForm

 

public partial class MainForm:Form

{

    ............

 

    private void menuItem1_Load(object sender,EventArgs e)    

     {

        ChildForm child1=ChildForm.Create();

        child1.show();

        child1.Focus();

     }

  

    //......

}

 

子窗体:ChildForm

 

public partial class ChildForm:Form

{

     .....

 

     static ChildForm child;

    

     Public static ChildForm Create()

      {

         if(child==null)

            child=new ChildForm();

          return Child;

      }

     ......

}

 

F5运行后,的确实现了上面提到的功能。然而,把子窗体关闭后,想再次打开该子窗体时,单击菜单项,会出现异常:ObjectDisposedException was unhandled.

 

        这是为什么呢??

 

    涉及到C#垃圾回收的问题:

 

    垃圾回收.NET运行库的一部分。垃圾回收器管理所有的托管对象,所有需要托管数据的.NET语言(包括 C#)都受运行库的垃圾回收器的制约。垃圾回收器可以确定运行垃圾回收的最佳时间,自动进行垃圾回收。然而垃圾回收的一个产物是:C# 对象没有确定性毁坏。child引用的Form对象关闭后变量child里的地址存放的是已经被disposed的object(或为其他数据),所以,再次访问child引用的Form对象时会产生ObjectDisposedException异常。
 

   怎么办??

 

   方法:应该先将Child引用置空(=null),然后创建新的Form实例供Child引用。

  途径有二:

方法一:

修改子窗体的构造函数,添加Form事件Disposed的处理函数。

public ChildForm()

{

      //.........

      this.Disposed+=new System.EventHandler(Form_Disposed);

}

然后事件Form_Disposed的处理函数

private void Form_Disposed(object sender,EventArgs e)

{

      Child=null;

}

方法二:

重写ChildFormOnClosed方法

Protected override void OnClosed(EventArgs e)
{

      base.OnClosed(e);  
     
child=null;

}

当然可能有其他的方法,各位看客有兴趣的话补充一下。另外有叙述不当的地方,请多多指教,在下感激不尽。

posted on 2007-01-08 16:29 王国正 阅读(2385) 评论(13)  编辑 收藏 网摘
评论
  • wuChang      
    Posted @ 2006-12-04 14:52
    既然是打开only one,那在OnClosing里处理更好些

    private void Form_OnClosing(.....)
    {
    e.Cancel = true;
    this.hide();
    }
      回复  引用  查看    
  • b[未注册用户]
    Posted @ 2006-12-04 15:56
    if(child==null && child.IsDisposed)
      回复  引用    
  • #3楼[楼主]
    王国正      
    Posted @ 2006-12-04 16:14
    先谢楼上各位的捧场!
    TO b(用户名挺怪异的,呵呵)
    应该是(child==null || child.IsDisposed)吧。
      回复  引用  查看    
  • yunhuasheng      
    Posted @ 2006-12-04 16:42
    分析的还好!
      回复  引用  查看    
  • b[未注册用户]
    Posted @ 2006-12-04 17:06
    呵呵,是写错了;
    这其实在现实是一样的,如果人死了,在还没有火化之前还是存在的.
    这儿人死是就窗体Cloes,火化就是GC了,所以你要问一下,那就应用IsDisposed了.
      回复  引用    
  • yzx110[匿名][未注册用户]
    Posted @ 2006-12-04 18:12
    这根垃圾收集没什么关系,

    你首先创建(Create)Form,然后关掉(Close),本来就被你Dispose了,你肯定不能再使用了。并且,因为Child不为null,GC根本没有影响到Child,更谈不上把Child自动设置为null了(GC不是这么工作的,只有设置了null,才被GC)。

    程序逻辑问题
      回复  引用    
  • Michael-_-Young      
    Posted @ 2006-12-05 08:54
    @yzx110[匿名]

    有道理
      回复  引用  查看    
  • minbear      
    Posted @ 2006-12-05 14:11
    这个问题由来已久,我一直的处理方式是用模态窗体,可以正常关闭.   回复  引用  查看    
  • .progame[未注册用户]
    Posted @ 2006-12-05 18:12
    不应该是垃圾回收的问题吧 应该是悬空指针的问题   回复  引用    
  • #10楼[楼主]
    王国正      
    Posted @ 2006-12-05 23:44
    首先承认错误:
        通过查找一些资料,我发现所叙述的问题的确不是垃圾回收的问题。
    感谢
        各位看客的鼓励和回复
        尤其是 b 形象的比喻,yzx110[匿名]一针见血的指出问题,.progame的观点,让我受益匪浅
    讨论点:
            yzx110[匿名]对GC的看法:只有设置了null,才被GC。我觉得值得推敲一下,当对象不再被任何变量引用时才可能会被GC。
            关闭窗口后再次打开的过程应该是这样:先将指针child悬空(引.progame的评论),然后将child指向new ChildForm()这个新的对象,打开的就是这个新对象。
          
       
        该观点有误处,希望各位看客斧正,谢谢先。

      回复  引用  查看    
  • maxxxz[未注册用户]
    Posted @ 2007-01-12 14:38
    我这里遇到一个问题。就是同样用这个单件模式。也判断IsDisposed了。但是我关闭窗体的时候就调用this.Close();进行关闭。但是很遗憾的是。这个窗体还是可以再次被Show出来。而且跟踪的时候发现IsDisposed还是为true。   回复  引用    
  • maxxxz[未注册用户]
    Posted @ 2007-01-12 14:39
    上面错了一点,IsDisposed表现是为false。没有被标记为释放   回复  引用    
  • MYGIS_3      
    Posted @ 2009-06-13 21:53
    我在引用作者上述的解决办法后,发现关闭child1后,child为null了,但是child1并没有为null啊!它们指向的不是同一地址吗?而作者的意图不正是要使child1也为null吗?但是我用的怎么不行呢?请指点一下,谢谢!   回复  引用  查看    



发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 581488




相关文章:

相关链接:

统计





其实每天都有很开心的事情
每天都可以很放松,很自信
每天都会有面包吃
有牛奶喝
有楼房住
只要我们愿意
只要我们愿意努力
只要我们愿意把这种努力作为人生旅途的快乐