Form1:   Form2 rf = new Form2();            if (rf.ShowDialog() == DialogResult.OK)
            {
                rf.Dispose();
                rf = null;
                GC.Collect();
            }
Form2只是一个简单的窗体,这时候查看物理内存状态,如果我不停的打开Form2并将之关闭,所占有的物理内存并不释放。盼高手回复!
开发环境wce 5.0

解决方案 »

  1.   


    GC.Collect();
    并不是马上执行~~~~
      

  2.   

    楼上要好好的看看.NET的内存管理了
    是可以自动的垃圾回收,但不是实时的
      

  3.   

    Form2   rf   =   new   Form2();                         if   (rf.ShowDialog()   ==   DialogResult.OK) 
                            { 
                                    rf.Dispose(); 
                                    rf   =   null; 
                                    GC.Collect();
                            } 
    -------------------------------------------------------------GC.Collect(); /////LZ难道认为在这里就释放?rf的作用域还没结束。垃圾回收一个重要的原则是:只要访问的到就不释放。很显然在if{}后rf还可以访问的到,所以无论你怎么操作都不会回收。你把rf   =   null; 注销掉,那么,在if{}后面rf里面的所有成员都可以访问到,不会释放。
      

  4.   

    楼上,看来你也看过书了。说的没错
    ///////////////////////////
    垃圾回收一个重要的原则是:只要访问的到就不释放。
    ///////////////////////////
    这里说的访问不到不是变量,是对象,释放的也是对象,不是变量,变量的内存是堆栈上的,Form2是个类型,这个是在程序堆上的。这个时候,已经没有任何的变量可以访问到这个new Form2对象了。这个对象已经是符合被回收条件了。此时调用GC.Collect()肯定会释放的。如下测试程序:
    //////////////////////////////////////////////////////using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;namespace WinceTestProject01
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }        MEMORYSTATUS mem1, mem2;
            private void button1_Click(object sender, EventArgs e)
            {
                GlobalMemoryStatus(ref mem1);
                Form2 frm = new Form2();
                frm.ShowDialog();
                frm.Dispose();
                frm = null;
                GC.Collect();
                GlobalMemoryStatus(ref mem2);
                MessageBox.Show(
                    (mem1.dwAvailPhys ).ToString() +
                    "\r\n" +
                    (mem2.dwAvailPhys ).ToString()
                );        }        [StructLayout(LayoutKind.Sequential)]
            public struct MEMORYSTATUS
            {
                public int dwLength;
                public int dwMemoryLoad;
                public int dwTotalPhys;
                public int dwAvailPhys;
                public int dwTotalPageFile;
                public int dwAvailPageFile;
                public int dwTotalVirtual;
                public int dwAvailVirtual;
            }        [DllImport("coredll.dll", EntryPoint = "GlobalMemoryStatus")]
            public static extern void GlobalMemoryStatus(
                ref MEMORYSTATUS lpBuffer
            );
        }    
    测试结果如下:17346560
    1728512017170432
    1717043217170432
    1721548817215488
    1721548817215488
    1721548817215488
    17215488单位是byte可见是会立刻回收的。
      

  5.   

    呵呵,查看内存大小是看不出什么问题来的,因为你根本不能判断垃圾回收到底回收了什么。你把窗口最大化与最小化,内存就会变化。就像你在餐馆里吃坏了肚子,你怎么知道是菜有问题还是盘子没洗干净?这样吧,程序添加一个窗体Form2,拖一个textbox,并设为public。如何代码如下
                Form2 rf = new Form2();
                rf.textBox1.Text = "123";
                if (true)
                {
                    rf.Dispose();
                    //rf = null;
                    GC.Collect();
                }
                string str = rf.textBox1.Text;
                MessageBox.Show(str);如果照你的意思,那么string str = rf.textBox1.Text;这一行就会报错,或者str为空。因为照你的理论已经会上了。
    自己看吧
      

  6.   

    你隐去了rf = null这步。这里没有调用垃圾回收。按我所说的。你执行了rf = null后,调用GC.Collect就会回收。你只调用了Dispose,这个一般是释放Graphic和消息队列的注册,以及其他注册的事件。我从来没说Dispose会释放内存啊。这个只是回收非托管资源,你不执行rf=null当然不释放,肯定啊。因为GC.Collect的时候发现new Form2依然被你的rf引用着的。
      

  7.   

    呵呵,查看内存大小是看不出什么问题来的,因为你根本不能判断垃圾回收到底回收了什么。你把窗口最大化与最小化,内存就会变化。 就像你在餐馆里吃坏了肚子,你怎么知道是菜有问题还是盘子没洗干净?
    这个看不出问题???.net内存是托管的没错。只是限於.net clr,那么,.net clr运行要内存不?如果实际的内存占用量减少了。你能说你的clr托管的内存他没释放?不释放实际内存怎么减少的?测试环境:wince 5.0
    打开我的电脑->根目录,启动程序,点击按钮操作。
      

  8.   

    rf = null
    首先你要明确rf只是个引用,为了方便理解,我们可以理解为rf为指向Form2对象的指针。
    rf置为null也仅仅是把这个引用置为空,但对象本身并没有销毁。直到作用域结束后才被销毁。看以下代码
                Form2 rf = new Form2();
                Form2 rf1 = null;
                rf.textBox1.Text = "123";
                if (true)
                {
                    rf.Dispose();
                    rf1 = rf;
                    rf = null;
                    GC.Collect();
                }
                string str = rf1.textBox1.Text;
      

  9.   

    服了楼上了。多简单个问题。我再重复一次,如果有引用变量指向这个对象,这个对象不会被释放。你这里用了个rf1,那rf=null当然还有引用指向这个new Form2()对象。实在不知道你后面还会帖个什么样的代码出来。你要理解了我的意思先。不要再换汤不换药的,我的意思,就是不要有任何引用指向这个new Form2对象。clear?诶。睡觉了。最后说一次。你这个代码和上面注释的那个一模一样。真不知道你怎么会回复这样一个莫名其妙的例子。如果我帖这个
    Form2 rf = new Form2(); 
                Form2 rf1 = null; 
                rf.textBox1.Text = "123"; 
                if (true) 
                { 
                    rf.Dispose(); 
                    rf1 = rf; 
                    rf = null; 
                    rf1 = null;   
                    GC.Collect(); 
                } 
                string str = rf1.textBox1.Text; 
    你是不是还搞个引用指向这个new Form2对象????
    仔细看看我的回复吧:
    //////////////////////////////////////////
    这里说的访问不到不是变量,是对象,释放的也是对象,不是变量,变量的内存是堆栈上的,Form2是个类型,这个是在程序堆上的。这个时候,已经没有任何的变量可以访问到这个new Form2对象了。这个对象已经是符合被回收条件了。此时调用GC.Collect()肯定会释放的。
    //////////////////////////////////////////
    重复了几次了。变量是在堆栈上分配的,new Form2是在堆上分配的,你保留指向堆上对象的引用。那垃圾回收肯定不会回收。你反复帖出这样的代码。我只能说你没看明白我帖的这段。其实你明白这个道理。但不知道你为什么非要弄这个例子,想说明什么?
      

  10.   

    我看楼上几位除了 wuyazhe 没人理解这个 GC.Collect() 究竟是怎么回事。请仔细阅读 SDK 里面专门的一节 “finalize 和 析构函数”,里面有 GC 的很清楚的功能说明,并且给出了手动释放资源——注意,没有说内存——的解决方案。看看下面的代码吧:
    1  using System.Data;2  public void MemoryTracking()
    3  {
    4      try
    5      {
    6          for (int i = 0; i < 100; i ++)
    7          {
    8              DataTable dt = new DataTable();
    9              fillTable(dt);
    10             
    11             dt.Dispose();
    12             dt = null;            
    13         }
    14     }
    15     catch(Exception ex)
    16     {
    17         throw (ex);
    18     }
    19 }private void fillTable(DataTable dt)
    {
        // 为 dt 创建10列,5000 条有数据的 DataRow
    }
    注意哦,如果吧第 8 行代码移动到第 6 行之前,那效果完全不一样哦。
      

  11.   

    rf = new Form2(); 
    if (rf.ShowDialog() == DialogResult.OK) 

        rf.Dispose(); 
        rf = null; 
        GC.Collect(); 
    }如果执行了 GC 那一句,内存就会回收,除非其他地方还有对窗体的引用。不知道楼主是怎么看内存的,任务管理器好像不大精确,销毁几个窗体不
    会收回大量内存,所以肉眼看不出来。可以一次创建1000个窗体,然后回
    收一下看有没有效果。免责声明:死机莫找俺^_^。祝楼主好运。