1.C#有自动垃圾回收的机制,但是它一般在什么时候回收呢.在当程序内存使用上升到某个值时会回收,还是程序运行过了一定时间后回收呢?
我这里有一个C#写的程序,是以系统服务运行的,一般不会重启,里面的函数在写的时候都没有专门的释放创建的对象。我想问一下长时间运行下去,会导致进程的内存使用率慢慢增加吗?2.我之前测试了一下,不断创建对象看什么时候会进行垃圾回收,发现在8G内存的服务器上运行我的测试程序,好像是每到150M内存左右的时候就会回收一下,回到70M左右继续增加到150M左右又进行一次...这个是依据什么来进行回收的呢?3.当调用完一个函数之后,这个函数里创建的对象是不是就变成可回收状态了呢?如果是静态方法的话是不是也这样呢?4.如果在函数return这一句之前加上GC.collect()来强制垃圾回收,那么它会回收这个函数前面创建的对象吗,我测试的感觉好像是不会,在函数最后一句加GC.collect()好像没有用,在调用这个函数之后加GC.collect()才可以。
但这样每次就要在调用函数之后再加上GC.collect()才行,会比较麻烦,有没有办法直接在函数中就做到呢。

解决方案 »

  1.   

    在GC.Colect方法被调用的时候回收垃圾,这个方法你可以调用,如果你不调用,系统在垃圾多得没法忍受的时候会在另一个线程调用,在GC.Colect方法被调用之前,所有引用对象都不会被释放,所以内存会缓慢增加,直到系统自动调用GC.Colect方法,这时候会生成很多碎片,所以如果你的程序分配的内存多而且频繁,最好自己选择一个适当的时机调用GC.Colect来释放内存,
      

  2.   

    >当调用完一个函数之后,这个函数里创建的对象是不是就变成可回收状态了呢?如果是静态方法的话是不是也这样呢?这个不一定,垃圾回收的规则是,如果没有任何引用指向某个对象,这个对象就会被视为垃圾,如果嗲用GC.Colect将会被回收,静态方法和普通方法是一样的,倒是静态变量和类的实例变量会影响垃圾回收,如果你用一个静态变量引用一个对象,那么它永远都不会被回收,因为c#检测到始终有一个静态变量引用它,就认为它是有用的,
     
      

  3.   

    调用GC.collect()的时候,会回收当前的所有垃圾,不管是不是本方法产生的垃圾,都会被回收,但GC回收的是垃圾而不是你创建的对象,你创建的对象不一定是垃圾,你创建的对象是否是垃圾,取决于是否还有变量在引用它,所以如果想让对象早一点被回收,你要经常清理类的引用变量和静态引用变量,比如 string a; 是类的一个字段,你在a没用的时候,来一句a=null,这样它之间指向的对象就可以被释放,否则GC会认为a还在指向这个对象,就不会释放它,
      

  4.   

    请问如果我在一个方法中创建了一个对象,但是没有设置它为null,那么在方法已经调用完执行结束后,是不是这个对象就处于没有被引用的状态呢?
    如果对象也都没有置null处理,但我是在函数内部最后的return之前调用,这时对象可以被回收吗?
    也就是下面两种情况,创建的MyObj对象会被GC.collect回收吗情况一:public void fun()
    {
      MyObj test = new MyObj();
      //.......
      return;
    }public void fun2()
    {
      fun();
      GC.collect();
    }
    情况二:public void fun()
    {
      MyObj test = new MyObj();
      //.......
      GC.collect();
      return;
    }
    public void fun2()
    {
      fun();
    }
      

  5.   

    public void fun()
    {
      MyObj test = new MyObj();
      //.......
      GC.collect();
      return;
    }
    调用GC.collect()时,test仍然有效,无法回收。
    情况一中因为超过作用域,可以被回收。
      

  6.   

    但是我现在遇到的情况是即使函数调用完了再回收,还是没效果.
    比如MyObj test = new MyObj();
    test.MyFunction();
    test = null
    GC.collect();即使是这样,我把方法放在类里,创建完对象后把对象设置为null,调用GC.collect()仍然不会回收.
    我创建循环调用它的话,就会看到内存一直在涨.
      

  7.   

    上面说的回收不是指回收test对象本身,这个不能回收我可以理解。
    但我是指的test.MyFunction方法中创建的对象也不能被回收,这些对象既不是静态的,也不是MyObj的成员变量,就是MyFunction里面定义的。
      

  8.   

    在.net中自动内存管理是由垃圾回收器来是实现,GC自动完成对托管堆管理。☞  什么样对象被GC来回收一个对象不被任何其他对象所引用时,GC采用一定的算法在托管堆中遍历所有对象,构成一个对象图,而不可以到达的对象将成为被释放的垃圾对象。☞ 如何回收每个应用程序都有一组根(指针),指向托管堆中的存储位置,有JIT编译器和CLR运行时维护根指针列表,主要包括全局变量,静态变量,局部变量和寄存器指针等。垃圾收集器就是通过指针列表来实现托管堆中的对象图,当垃圾回收器启动时,它假设所有对象都是可回收的垃圾,然后开始遍历所有的根,将根引用的对象标记为可达对象图中,依次类推,垃圾收集器通过根列表的递归遍历,将能找到的所有可达对象,形成一个可达图。同时不可到达的对象则认为是可回收的对象。这种算法一般称为:标记和清除算法。☞ 何时回收内存收集器周期性的执行内存清楚工作,一般以下方式启动垃圾收集器:  第0代(代龄)对象充满时,
      强制执行GC.Collect方法,
      windows报告内存不足,CLR将强制执行垃圾回收。
      CLR卸载AppDomain时,GC将对所有代龄的对象执行垃圾回收。 简单介绍一下代龄:垃圾收集器将托管堆中的对象分为三代:0(容量256KB),1(容量2MB),2(容量10MB),其中第0代对象的回收的效率最高,CLR初始化后,被添加到托管堆中的对象都被定为第0代,当有垃圾回收执行时,未被回收的对象代龄将提升一级,变成第1代对象,而后新建的对象仍为第0代对象。也就是说代龄越小,表示对象越新,通常情况下生命周期越短。因此垃圾收集器总是首先回收第0代的不可到达对象的内存。那对1代对象的收集是什么时候呢?第0代对象内存不足以创建新的对象,同时第1代对象的体积也超出了容量值时,垃圾回收器将同时对0代和1代对象进行垃圾回收。回收后未被收回的1代对象升级为2代对象,未被回收的0代对象升级为1代对象,而后新建的对象仍为第0代。垃圾收集正式上述过程的不断重复。 以上都是涉及是关于.net对于托管资源的回收,至于对于非托管的资源(包括数据库连接,文件句柄,网络连接,COM对象等)是利用2种方式(Finalize和Dispose)来实现的,具体就不说了。