zoukankan      html  css  js  c++  java
  • (转)C#在父窗口中调用子窗口的过程(无法访问已释放的对象)

    C#在父窗口中调用子窗口的过程:
    1、 创建子窗口对象
    2、 显示子窗口对象
     
    笔者的程序中,主窗体MainFrm通过菜单调用子窗口ChildFrm。在窗体中定义了子窗口对象,然后在菜单项点击事件中,加入了如下代码来创建和显示子窗口:
     
    Private childFrm myChildFrm = null//定义子窗口对象
    private void OpenChildFrmToolStripMenuItem_Click(object sender, EventArgs e)
    {
            myChildFrm 
    = new ChildFrm();//创建子窗口对象
            myChildFrm.Show();//显示子窗口
            myChildFrm.Focus();//使子窗口获得焦点
    }
     
     
     
    当点击菜单中的OpenChild项时,创建了子窗口并显示在最前面。此时如果关闭子窗口再点击菜单打开,不会有问题。但是如果子窗口没有关闭的情况下,再次点击菜单中的OpenChild项,则会再创建一个子窗口。两个子窗口具有相同的内容,这不是我们所希望看到的。
     
    为此,对菜单项点击事件做如下改进:
     
    private void OpenChildFrmToolStripMenuItem_Click(object sender, EventArgs e)
    {
        
    if(myChildFrm != null)
        
    {
            myChildFrm.Show();
    //显示子窗口
            myChildFrm.Focus();//使子窗口获得焦点
        }

        
    else
        
    {
            myChildFrm 
    = new ChildFrm();//创建子窗口对象
            myChildFrm.Show();//显示子窗口
            myChildFrm.Focus();//使子窗口获得焦点
        }

    }

    这样修改的目的是:当子窗口对象存在时,直接显示子窗口。当子窗口不存在时,创建子窗口,然后再显示。
     
    现 在来检验效果:当第一次点击OpenChild菜单项时,创建子窗口并正确显示。不关闭子窗口的情况下再点击OpenChild菜单项,子窗口只显示了一 个,说明按预期工作了。现在,我们关闭子窗口,再点击OpenChild菜单项,程序在运行到下面这个语句时出现“未处理 ObjectDisposedException”异常。
     
    if(myChildFrm != null)
    {
        myChildFrm.Show();//显示子窗口
     
    错误信息:无法访问已释放的对象。对象名:“childFrm”。
     
     
    这就让人奇怪了。如果子窗口没有被销毁,那它就应该能够正确显示。点击了关闭子窗口,显然应该子窗口已经销毁了,按理myChildFrm等于null,运行的时候应该直接运行else后面的语句块,为什么却进入了满足myChildFrm!=null的语句块呢?
     
    其实,这个问题与C#的垃圾回收有关。垃圾回收器管 理所有的托管对象,所有需要托管数据的.NET语言(包括 C#)都受运行库的垃圾回收器的制约。垃圾回收器可以确定运行垃圾回收的最佳时间,自动进行垃圾回收。然而垃圾回收的一个产物是:C#对象没有确定性毁 坏。所以会出现子窗口对象已被销毁,但又不为null,故出现访问时产生“未处理 ObjectDisposedException”异常(来自于“从小处看C#.net垃圾回收”一文)。
     
    如何解决这个题,有人提出:应该应该彻底回收Child所占的资源。并提供了解决方法(请搜索“从小处看C#.net垃圾回收”查看相关情况)。
     
    其实,现在我们需要解决的问题仅仅是:子窗口已经被销毁,但对象却不为null。只需要对你窗口中的菜单点击事件函数进行简单修改就可以了。
     
    private void OpenChildFrmToolStripMenuItem_Click(object sender, EventArgs e)
    {
        
    if(myChildFrm != null)
        
    {
              
    if(myChildFrm.IsDisposed)
                      myChildFrm 
    = new ChildFrm();//
    如果已经销毁,则重新创建子窗口对象
              myChildFrm.Show();
              myChildFrm.Focus();
         }

        
    else
        
    {
            myChildFrm 
    = new ChildFrm();
            myChildFrm.Show();
            myChildFrm.Focus();
        }

    }

    前面这是按逻辑的方式进行思考的,显示子窗口和获得焦点两行是重复的,两个if语句也可以做一下简化。指定子窗口和父窗口的父子关系。最后的结果是这样:
     
    private void OpenChildFrmToolStripMenuItem_Click(object sender, EventArgs e)
    {
        
    if(myChildFrm == null || myChildFrm.IsDisposed)
        
    {  
            myChildFrm 
    = new ChildFrm();
        }

        myChild..MdiParent = this; //建立父子关系

            myChildFrm.Show(); //显示子窗口
        myChildFrm.Focus();  //子窗口获得焦点
    }
     
     
     
    这样,就能够如我们如愿般调用子窗口了。
  • 相关阅读:
    数据库与数据仓库的比较Hbase——Hive
    log4j 配置使用
    hadoop Datanode Uuid unassigned
    kafka相关文章引用
    kafka可靠性
    kafka基本原理
    html
    并发编程
    Python之系统交互(subprocess)
    网络编程
  • 原文地址:https://www.cnblogs.com/newmanzhang/p/3433930.html
Copyright © 2011-2022 走看看