(转)C#在父窗口中调用子窗口的过程(无法访问已释放的对象)
2013-11-20 17:01
357 查看
C#在父窗口中调用子窗口的过程:
1、 创建子窗口对象
2、 显示子窗口对象
笔者的程序中,主窗体MainFrm通过菜单调用子窗口ChildFrm。在窗体中定义了子窗口对象,然后在菜单项点击事件中,加入了如下代码来创建和显示子窗口:
Private childFrm myChildFrm = null; //定义子窗口对象
private void OpenChildFrmToolStripMenuItem_Click(object sender, EventArgs e)
private void OpenChildFrmToolStripMenuItem_Click(object sender, EventArgs e)
[align=left]这样修改的目的是:当子窗口对象存在时,直接显示子窗口。当子窗口不存在时,创建子窗口,然后再显示。[/align]
[align=left] [/align]
[align=left]现 在来检验效果:当第一次点击OpenChild菜单项时,创建子窗口并正确显示。不关闭子窗口的情况下再点击OpenChild菜单项,子窗口只显示了一 个,说明按预期工作了。现在,我们关闭子窗口,再点击OpenChild菜单项,程序在运行到下面这个语句时出现“未处理 ObjectDisposedException”异常。[/align]
[align=left] [/align]
[align=left]if(myChildFrm != null)[/align]
[align=left]{[/align]
[align=left] myChildFrm.Show();//显示子窗口[/align]
[align=left] [/align]
[align=left]错误信息:无法访问已释放的对象。对象名:“childFrm”。[/align]
[align=left] [/align]
[align=left] [/align]
[align=left]这就让人奇怪了。如果子窗口没有被销毁,那它就应该能够正确显示。点击了关闭子窗口,显然应该子窗口已经销毁了,按理myChildFrm等于null,运行的时候应该直接运行else后面的语句块,为什么却进入了满足myChildFrm!=null的语句块呢?[/align]
[align=left] [/align]
[align=left]其实,这个问题与C#的垃圾回收有关。垃圾回收器管 理所有的托管对象,所有需要托管数据的.NET语言(包括 C#)都受运行库的垃圾回收器的制约。垃圾回收器可以确定运行垃圾回收的最佳时间,自动进行垃圾回收。然而垃圾回收的一个产物是:C#对象没有确定性毁 坏。所以会出现子窗口对象已被销毁,但又不为null,故出现访问时产生“未处理 ObjectDisposedException”异常(来自于“从小处看C#.net垃圾回收”一文)。[/align]
[align=left] [/align]
[align=left]如何解决这个题,有人提出:应该应该彻底回收Child所占的资源。并提供了解决方法(请搜索“从小处看C#.net垃圾回收”查看相关情况)。[/align]
[align=left] [/align]
[align=left]其实,现在我们需要解决的问题仅仅是:子窗口已经被销毁,但对象却不为null。只需要对你窗口中的菜单点击事件函数进行简单修改就可以了。[/align]
[align=left] [/align]
private void OpenChildFrmToolStripMenuItem_Click(object sender, EventArgs e)
[align=left]前面这是按逻辑的方式进行思考的,显示子窗口和获得焦点两行是重复的,两个if语句也可以做一下简化。指定子窗口和父窗口的父子关系。最后的结果是这样:[/align]
[align=left] [/align]
private void OpenChildFrmToolStripMenuItem_Click(object sender, EventArgs e)
myChildFrm.Show(); //显示子窗口
myChildFrm.Focus(); //子窗口获得焦点
}
[align=left] [/align]
[align=left] [/align]
[align=left] [/align]
[align=left]这样,就能够如我们如愿般调用子窗口了。[/align]
1、 创建子窗口对象
2、 显示子窗口对象
笔者的程序中,主窗体MainFrm通过菜单调用子窗口ChildFrm。在窗体中定义了子窗口对象,然后在菜单项点击事件中,加入了如下代码来创建和显示子窗口:
Private childFrm myChildFrm = null; //定义子窗口对象
private void OpenChildFrmToolStripMenuItem_Click(object sender, EventArgs e)
private void OpenChildFrmToolStripMenuItem_Click(object sender, EventArgs e)
[align=left]这样修改的目的是:当子窗口对象存在时,直接显示子窗口。当子窗口不存在时,创建子窗口,然后再显示。[/align]
[align=left] [/align]
[align=left]现 在来检验效果:当第一次点击OpenChild菜单项时,创建子窗口并正确显示。不关闭子窗口的情况下再点击OpenChild菜单项,子窗口只显示了一 个,说明按预期工作了。现在,我们关闭子窗口,再点击OpenChild菜单项,程序在运行到下面这个语句时出现“未处理 ObjectDisposedException”异常。[/align]
[align=left] [/align]
[align=left]if(myChildFrm != null)[/align]
[align=left]{[/align]
[align=left] myChildFrm.Show();//显示子窗口[/align]
[align=left] [/align]
[align=left]错误信息:无法访问已释放的对象。对象名:“childFrm”。[/align]
[align=left] [/align]
[align=left] [/align]
[align=left]这就让人奇怪了。如果子窗口没有被销毁,那它就应该能够正确显示。点击了关闭子窗口,显然应该子窗口已经销毁了,按理myChildFrm等于null,运行的时候应该直接运行else后面的语句块,为什么却进入了满足myChildFrm!=null的语句块呢?[/align]
[align=left] [/align]
[align=left]其实,这个问题与C#的垃圾回收有关。垃圾回收器管 理所有的托管对象,所有需要托管数据的.NET语言(包括 C#)都受运行库的垃圾回收器的制约。垃圾回收器可以确定运行垃圾回收的最佳时间,自动进行垃圾回收。然而垃圾回收的一个产物是:C#对象没有确定性毁 坏。所以会出现子窗口对象已被销毁,但又不为null,故出现访问时产生“未处理 ObjectDisposedException”异常(来自于“从小处看C#.net垃圾回收”一文)。[/align]
[align=left] [/align]
[align=left]如何解决这个题,有人提出:应该应该彻底回收Child所占的资源。并提供了解决方法(请搜索“从小处看C#.net垃圾回收”查看相关情况)。[/align]
[align=left] [/align]
[align=left]其实,现在我们需要解决的问题仅仅是:子窗口已经被销毁,但对象却不为null。只需要对你窗口中的菜单点击事件函数进行简单修改就可以了。[/align]
[align=left] [/align]
private void OpenChildFrmToolStripMenuItem_Click(object sender, EventArgs e)
[align=left]前面这是按逻辑的方式进行思考的,显示子窗口和获得焦点两行是重复的,两个if语句也可以做一下简化。指定子窗口和父窗口的父子关系。最后的结果是这样:[/align]
[align=left] [/align]
private void OpenChildFrmToolStripMenuItem_Click(object sender, EventArgs e)
myChildFrm.Show(); //显示子窗口
myChildFrm.Focus(); //子窗口获得焦点
}
[align=left] [/align]
[align=left] [/align]
[align=left] [/align]
[align=left]这样,就能够如我们如愿般调用子窗口了。[/align]
相关文章推荐
- C#在父窗口中调用子窗口的过程(无法访问已释放的对象)异常,不存在从对象类型System.Windows.Forms.DateTimePicker到已知的托管提供程序本机类型的映射。
- C#在父窗口中调用子窗口的过程(无法访问已释放的对象)
- C#在父窗口中调用子窗口的过程(无法访问已释放的对象)
- C# WinForm:无法访问已释放的对象
- C#主窗体控件打开一个子窗体,子窗体关闭后,再重新打开子窗体出现:无法访问已经释放的对象
- winform 调用 this.invoke 出错 无法访问已释放的对象
- C# Socket连接 无法访问已释放的对象
- c#重新打开子窗体出现无法访问已释放对象的异常
- C#技巧【调用线程无法访问此对象,因为另一个线程拥有该对象的问题的解决办法】【C#读写EXCEL源码提示“office检测到此文件存在一个问题。为帮助保护您的计算机,不能打开此文件”的解决】
- 调用线程无法访问此对象,因为另一个线程拥有该对象 [c# wpf定时器程序报的错误]
- C# Socket连接 无法访问已释放的对象
- C#线程无法访问已释放的对象
- C# WeifenLuo.WinFormsUI.Docking.dll 应用之问题集 控件无法访问已释放的对象。
- 【C#】更新界面显示并解决this.Invoke无法访问已释放的对象
- C#主窗体控件打开一个子窗体,子窗体关闭后,再重新打开子窗体出现:无法访问已经释放的对象
- WPF [调用线程无法访问此对象,因为另一个线程拥有该对象。] 解决方案以及如何实现字体颜色的渐变
- WPF中调用线程无法访问此对象,因为另一个线程拥有该对象 的解决方法
- Flex4 主程序调用模块方法报TypeError: Error #1009:无法访问空对象引用的属性或方法
- WPF异常:调用线程无法访问此对象,因为另一个线程拥有该对象。
- 用了invoke还是出错的解决方法.wpf 调用线程无法访问此对象,因为另一个线程拥有该对象。