Form.Close后Form里面的非托管资源是立刻释放了,只是托管资源到GC.Collect()才会真正释放

解决方案 »

  1.   

    close() 和 Dispose()是不一样的。Dispose 会释放所有的正在使用的资源。
      

  2.   

    嗯,这问题不错,微软的解释是“在以下两种情况下调用 Close 不会释放窗体:(1) 窗体是多文档界面 (MDI) 应用程序的一部分且是不可见的;(2) 您是使用 ShowDialog 显示的该窗体。 在这些情况下,需要手动调用 Dispose 来将窗体的所有控件都标记为需要进行垃圾回收。”
      

  3.   

    因为子窗体是在主窗体中new的,所以得等到代码执行完毕才会释放.
    而模式窗体阻止了主窗体代码的继续执行,只有等窗体关闭代码才会继续执行.相比模式窗体,非模式窗体在主窗体代码已经执行完毕的情况下还能继续存在,不是更神奇?
      

  4.   

    模式窗体frm没有释放了,你怎么能在主窗体中接收值呢,if (result ==DialogResult.OK)
      

  5.   

    this.DialogResult = DialogResult.OK;并没有释放窗体。
      

  6.   

    close 会释放非托管资源,不会释放form对象
      

  7.   

    后面还有这句:this.Close();  我忘了加
      

  8.   

    哪些是非托管资源?哪些又是托管资源?
    好比你有一个Thread 托管对象,这个对象内部持有这非托管资源,一个内核对象,线程都是操作系统的内核对象,c#的Thread类只是对其作了一个包装。当你调用thread对象的dispose方法的时候,内核对象被释放,操作系统回收内核对象。但是你的托管thread对象还被你持有,你还可以访问它的属性和方法,但大多数方法和属性都会抛出objectdisposedexception。
    对于window窗体来说也是,window类其实也是对非托管资源的一些封装。当你调用Close的时候,其实窗体内部的资源也被释放了,记住任何时候调用Dispose方法,都是即释放托管资源,也释放非托管资源。你的问题来了,既然都释放了,那为什么我还可以访问这个window对象,答案是,被释放的资源是Window对象使用的资源,而非Window对象本身,你还可以访问这个Window对象,但是仅仅限于那些不依赖被释放资源的属性和方法。不信的话,当你在调用Close之后,再调用Show,你就知道结果了。
      

  9.   

    哪些是非托管资源?哪些又是托管资源?托管资源指的是.NET可以自动进行回收的资源,主要是指托管堆上分配的内存资源。托管资源的回收工作是不需要人工干预的,有.NET运行库在合适调用垃圾回收器进行回收。 非托管资源指的是.NET不知道如何回收的资源,最常见的一类非托管资源是包装操作系统资源的对象,例如文件,窗口,网络连接,数据库连接,画刷,图标等
      

  10.   


    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[]关键字
      

  11.   


    // 其次我想说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)(监测一个对象),等待远程汇编代码调用执行完毕// 小弟学如艺不精,如有错误,请勿见怪,大神也可指点一二
      

  12.   

    你就是被”释放“这两个字给害的。过度瞎猜”释放“的含义,就会产生歧义。别说是Close之后对象仍然在运行,就是执行Dispose之后对象也还是在运行啊。你应该客观的理解Close是干什么的,不要过度理解。同样地,也不要想有些人那样过度理解Dispose的含义。
      

  13.   

    遇到有人说什么Dispose是”释放资源“,我建议你就问问他”具体释放了什么资源,你有办法查到吗“?看看他有没有查过!实际上,在Dispose代码中的源代码可以看到,因此可以非常清楚地根据代码来说出不同的对象(类)在Dispose方法中执行了什么清理动作。但是有人喜欢空洞地说什么”Dispose方法释放了.net对象的资源“这种空话,这就非常容易造成误解。不提空洞的”释放资源“这个坑爹的词儿,我可以肯定地说,你就能够更好地学习.net。另外要强调的是,GC会自动调用Dispose方法。所以你不需要调用对象的Dispose方法,它也会迟早被自动调用。(Dispose方法中通知GC不需要重复第二次调用Dispose方法,这是一个优化措施,并不改变这个逻辑)。
      

  14.   

    Close就是干Close的事情,而Dispose就是干Dispose的事情。你理解的那种”模式窗体frm释放“的概念,根本不是这两个东西。你只要去问问这两个方法内部到底干了什么,就不会再想去简单地学人家说”释放“这个词儿了。