关于模式窗口this.Close()后窗体是释放了吗?

jsjisweet 2014-06-24 10:18:58
今天看到一个项目代码,其中 它 在主窗体一个按钮事件 中新建了一个模式窗体:
DialogResult result = frm.ShowDialog();

然后在模式窗体执行完毕前给模式窗体frm的两个属性赋值:
this._title = model.ScriptTitle;
this._message = model.ScriptMsg;

然后:
 this.DialogResult = DialogResult.OK;


然后奇怪的是 主窗体居然可以通过 frm.Title,frm.Message 接收到这两个值?如下:
 if (result ==DialogResult.OK)
{
//表示用户成功更新了当前节点,刷新数据

treeView1.SelectedNode.Text = frm.Title;
textBox1.Text = frm.Message;
}

我就疑问了,模式窗体frm不是已经this.close()关闭了吗? 怎么还能在主窗体接受到值? 难道模式窗体frm没有释放?
...全文
1568 19 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
有心人问道 2015-08-19
  • 打赏
  • 举报
回复
sp1234 你好,我也想请教一下模态窗体的问题,我在CAD中如果调用了wpf窗体,偶尔会出现线程被占用之类的,然后软件就直接被卡死。如果用winform就不会。而且我没有直接调用过线程类。
jsjisweet 2014-06-24
  • 打赏
  • 举报
回复
引用 8 楼 chenzhihuasilao 的回复:
this.DialogResult = DialogResult.OK;并没有释放窗体。
后面还有这句:this.Close(); 我忘了加
angel6709 2014-06-24
  • 打赏
  • 举报
回复
close 会释放非托管资源,不会释放form对象
jsjisweet 2014-06-24
  • 打赏
  • 举报
回复
引用 2 楼 hbu_pig 的回复:
Form.Close后Form里面的非托管资源是立刻释放了,只是托管资源到GC.Collect()才会真正释放
哪些是非托管资源?哪些又是托管资源?
chenzhihuasilao 2014-06-24
  • 打赏
  • 举报
回复
this.DialogResult = DialogResult.OK;并没有释放窗体。
wangnaisheng 2014-06-24
  • 打赏
  • 举报
回复
模式窗体frm没有释放了,你怎么能在主窗体中接收值呢,if (result ==DialogResult.OK)
於黾 2014-06-24
  • 打赏
  • 举报
回复
因为子窗体是在主窗体中new的,所以得等到代码执行完毕才会释放. 而模式窗体阻止了主窗体代码的继续执行,只有等窗体关闭代码才会继续执行. 相比模式窗体,非模式窗体在主窗体代码已经执行完毕的情况下还能继续存在,不是更神奇?
  • 打赏
  • 举报
回复
Close就是干Close的事情,而Dispose就是干Dispose的事情。 你理解的那种”模式窗体frm释放“的概念,根本不是这两个东西。你只要去问问这两个方法内部到底干了什么,就不会再想去简单地学人家说”释放“这个词儿了。
  • 打赏
  • 举报
回复
遇到有人说什么Dispose是”释放资源“,我建议你就问问他”具体释放了什么资源,你有办法查到吗“?看看他有没有查过! 实际上,在Dispose代码中的源代码可以看到,因此可以非常清楚地根据代码来说出不同的对象(类)在Dispose方法中执行了什么清理动作。但是有人喜欢空洞地说什么”Dispose方法释放了.net对象的资源“这种空话,这就非常容易造成误解。 不提空洞的”释放资源“这个坑爹的词儿,我可以肯定地说,你就能够更好地学习.net。 另外要强调的是,GC会自动调用Dispose方法。所以你不需要调用对象的Dispose方法,它也会迟早被自动调用。(Dispose方法中通知GC不需要重复第二次调用Dispose方法,这是一个优化措施,并不改变这个逻辑)。
我现在在路上 2014-06-24
  • 打赏
  • 举报
回复
引用 2 楼 hbu_pig 的回复:
Form.Close后Form里面的非托管资源是立刻释放了,只是托管资源到GC.Collect()才会真正释放
xdashewan 2014-06-24
  • 打赏
  • 举报
回复
嗯,这问题不错,微软的解释是“在以下两种情况下调用 Close 不会释放窗体:(1) 窗体是多文档界面 (MDI) 应用程序的一部分且是不可见的;(2) 您是使用 ShowDialog 显示的该窗体。 在这些情况下,需要手动调用 Dispose 来将窗体的所有控件都标记为需要进行垃圾回收。”
  • 打赏
  • 举报
回复
close() 和 Dispose()是不一样的。Dispose 会释放所有的正在使用的资源。
欢乐的小猪 2014-06-24
  • 打赏
  • 举报
回复
Form.Close后Form里面的非托管资源是立刻释放了,只是托管资源到GC.Collect()才会真正释放
tinydyw 2014-06-24
  • 打赏
  • 举报
回复
没有...虽然不太懂c#的垃圾回收机制 不过这个时候窗体实例应该是还在内存中的....
  • 打赏
  • 举报
回复
你就是被”释放“这两个字给害的。过度瞎猜”释放“的含义,就会产生歧义。 别说是Close之后对象仍然在运行,就是执行Dispose之后对象也还是在运行啊。你应该客观的理解Close是干什么的,不要过度理解。同样地,也不要想有些人那样过度理解Dispose的含义。
相思梦 2014-06-24
  • 打赏
  • 举报
回复
// 其次我想说Net的内存进行回收并非真正是被回收,在GC进行回收时实际上是进行的内存清零(Zero)操作 // 首先Net在程序运行时则自动在内存中分配一块区域用于Net程序的内存模块,根据程序所需内存重进行 // 内存申请,实际上Net在分配内存时所分配的函数为HeapAlloc/GlobalAlloc/LocalAlloc,没有叫做栈这个 // 概念,栈不过是内存中一块受保护区域,能够完成他的函数只有HeapAlloca // VirtualAlloc在虚拟内存堆中分配,不过根据我研究Net内存申请形式时,已掐断这个申请概念,Net // 不可能再虚拟内存中进行申请,所以能够可选的只有 堆栈/全局/局部 分配申请 // Net对象在通过new关键字创建时Net在Net堆上的维指针会向下移动,因为这是Net提前申请好 // 的内存块只需要向下进行移动hMem指针即可,Net在内存中分配的方式是连续的,我相信用C#玩指针的 // 人因该会注意到,当然我不是说的IntPtr指针,而是C系列语言通用指针*,其次在Net程序打断点掐断 // 可以看见(返汇编)面板代码ASM/ARM嵌入式代码原型,其中(Rsp)这个点我相信因该属于Net指针在内存中欲分配维指针 // 其次深讨JIT虚拟机是如何解释字节代码并让进程执行的,我稍略有研究 // JIT虚拟机属于动态将IL元元素计算为Byte字节代码通过远程嵌入式汇编技术进行调用,所以在IL代码原型中所有 // 的一切皆为方法体,而不是在C#可见得属性事件等等,不过我曾利用C#对自身进行动态嵌入式汇编技术,不过答案 // 有些让我无法接受,( 内存写入错误,因为这是一块受保护内存区域 ),当然我对C++/易语言/EPL程序进行过远程汇编 // 答案是可行,汇编/嵌入式 不过如今玩半年多C#能够记下的机器代码早已经忘得差不多,不过也无所谓并不打算 // 从事C++更不打算做ARM,我可以给于一些原型帮助你们理解远程汇编,可以说本地汇编是最简单的尤其是静态汇编只需要在 // _asm{ 机器代码 };编译前置入则可以,如果是动态汇编必须申请一块内存区域作代码的实现块,将汇编代码计算出对应的 // 字节代码写进,并通过CallWindowProc调用汇编代码,如果是远程汇编,我比较喜欢用 VirtualAllocEx 在其他进程 // 申请虚拟内存,使用OpenProcess(打开进程)搭配WriteProcessMemory(写到内存)并调用CreateRemoteThread(在另一进程中 // 建立线程线索),前提是GetModuleHandleA加载模块User32.DLL并通过GetProcAddress获取到的CallWindowProcA函数指针 // hRemoteThread = CreateRemoteThread (进程句柄, 0, 0, CallWindowProc函数指针, 汇编远程代码指针, 0, 0)// NULL=0 // 其次则是WaitForSingleObject(hRemoteThread, -1)(监测一个对象),等待远程汇编代码调用执行完毕 // 小弟学如艺不精,如有错误,请勿见怪,大神也可指点一二
相思梦 2014-06-24
  • 打赏
  • 举报
回复
this->Close(); // this.Close(); // 首先调用对象的终结器( Finalize ),也就是传说中的( ~virtual className )析构函数(C# / C++) // 不过这里被释放掉的是非托管资源,并等待调用对象继承自( IDisposable )接口的( Dispose )方法 // 前提是你自身已经实现( IDisposable ),在( Dispose )方法中会设置GC.SuppressFinalize(this) // 禁止GC再次调用( Finalize ),通知GC进行回收( GC.Collect ),不过并不不是立即会被回收 // 如果你想立即回收再C#里面那是不可能,当然在C++/CLR里面可以立即回收Net/Win32资源 // 使用到delete / delete[]关键字
欢乐的小猪 2014-06-24
  • 打赏
  • 举报
回复
引用 9 楼 jsjisweet 的回复:
[quote=引用 2 楼 hbu_pig 的回复:] Form.Close后Form里面的非托管资源是立刻释放了,只是托管资源到GC.Collect()才会真正释放
哪些是非托管资源?哪些又是托管资源?[/quote]托管资源指的是.NET可以自动进行回收的资源,主要是指托管堆上分配的内存资源。托管资源的回收工作是不需要人工干预的,有.NET运行库在合适调用垃圾回收器进行回收。 非托管资源指的是.NET不知道如何回收的资源,最常见的一类非托管资源是包装操作系统资源的对象,例如文件,窗口,网络连接,数据库连接,画刷,图标等
月影 2014-06-24
  • 打赏
  • 举报
回复
引用 9 楼 jsjisweet 的回复:
[quote=引用 2 楼 hbu_pig 的回复:] Form.Close后Form里面的非托管资源是立刻释放了,只是托管资源到GC.Collect()才会真正释放
哪些是非托管资源?哪些又是托管资源?[/quote] 好比你有一个Thread 托管对象,这个对象内部持有这非托管资源,一个内核对象,线程都是操作系统的内核对象,c#的Thread类只是对其作了一个包装。当你调用thread对象的dispose方法的时候,内核对象被释放,操作系统回收内核对象。但是你的托管thread对象还被你持有,你还可以访问它的属性和方法,但大多数方法和属性都会抛出objectdisposedexception。 对于window窗体来说也是,window类其实也是对非托管资源的一些封装。当你调用Close的时候,其实窗体内部的资源也被释放了,记住任何时候调用Dispose方法,都是即释放托管资源,也释放非托管资源。你的问题来了,既然都释放了,那为什么我还可以访问这个window对象,答案是,被释放的资源是Window对象使用的资源,而非Window对象本身,你还可以访问这个Window对象,但是仅仅限于那些不依赖被释放资源的属性和方法。不信的话,当你在调用Close之后,再调用Show,你就知道结果了。

111,111

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧