CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
可用分押宝游戏火热进行中... 专题改版:Java Web 专题
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  .NET技术 >  VB.NET

关于WINFORM中的两个窗体之间释放内存的讨论,来着有份阿

楼主terryxin(南方窗口)2004-08-02 20:59:19 在 .NET技术 / VB.NET 提问

Dim   frm2   As   Object  
      frm2   =   New   Form2()  
      frm2.Show()  
      Me.Hide()  
      Me.Enabled   =   False  
      me.close()  
   
  我在window项目中遇到过这样得问题,web项目中没有遇到过,很正常。  
  window项目中得解决方法是:  
  在每个类的析构函数中将类里用到的class全部手工释放“   clsB   =   null;   ”  
  public   class   A  
  {  
        classB   clsB   =   new   classB();...  
   
        public   A()  
        {  
          }  
        ~public   A()  
        {  
              clsB   =   null;  
        }  
  }  
  每个类都这么处理,然后我的内存很正常,那个windows项目是个服务程序,整月整月的跑,再也没出现内存增长的情况。  
  希望谁能解释一下上面的用VB.NET怎么实现,  
  问题点数:200、回复次数:61Top

1 楼terryxin(南方窗口)回复于 2004-08-02 21:10:09 得分 0

大对象并不是不被   GC   管理,GC   管理大对象与管理小对象采用不同的堆,也就是说,在实际运行时,GC   管理两个对象堆。  
   
  大对象是指在   85000   字节及以上的对象。大对象是未精简的,且从开始创建时就被认为第   2   代的。   因为大对象的回收操作对性能有较大影响,不能频繁地对大对象进行回收。  
   
  GC   只在内存不够时,才会进行垃圾内存回收,具体的回收算法涉及到“代”这一个概念。  
  共有   3   个代,分别以   0、1、2   来表示。其中   0   代是最早发生,也是最频繁的,容量也是最小的,第   2   代则最迟发生,最不频繁,容量也是最大的,第   1   代介于两者之间。  
   
  其简要算法:  
  当第   0   代满时,才进行第   0   代回收,不能被回收的对象升为第   1   代。如果此时第   1   代满的话,就进行第   1   代回收。第   1   代回收后,不能被回收的对象升为第   2   代,如果此时第   2   代满的话,就进行第   2   代的回收。  
   
  在此期间,GC   会根据实际情况自适应地调整每代的容量阈值。典型的第   0   代在   256   KB   左右,第   1   代在   1   MB   左右,第   2   代在   10   MB   左右。但这个值并不是恒定,而是动态修整的。  
   
  注意,一个   30   MB   的   DataSet   并不一定就是大对象。因为此   DataSet   内部其实是大量引用其它对象的变量或域,未必就会达到   85000   字节。  
   
  如果是小对象,在运行过程中,此   DataSet   对象很可能会被移入第   1   代或者第   2   代,那么从以上的算法,应该看得出,在时间上是有一个明显的延迟的。如果移入第   2   代,则时间的延迟将更长。如果运行机器的物理内存配置较高的话,延迟时间也会相应较长一些。  
   
  如果是大对象,此   DataSet   对象将处于第   2   代上,回收的时间延迟当然就会比较长了。  
   
  所以,Dispose   后并不意味着垃圾内存会被立即回收,因为启动垃圾回收,是有一定算法要求的。  
   
  然而,程序员还是可以控制   GC   的,就是使用   GC.Collect(int)   方法,来显式启动   GC。  
  但程序员不能滥用此方法,因为此方法频繁执行会导致程序性能的明显下降。  
  GC.Collect(0);   //   立即回收第   0   代的垃圾内存  
  GC.Collect(1);   //   立即回收第   0   代、第   1   代的垃圾内存  
  GC.Collect(2);   //   立即回收所有垃圾内存  
   
  本例中,我认为可以使用   GC.Collect,因为此   DataSet   对象实在太多地占用内存。当调用   Dispose   后,调用一下   GC.Collect(2);可以明显将内存使用量降下来。  
   
  如果对象支持   Dispose   事件,也可在此事件中调用。  
   
  警告:不能滥用   GC.Collect,否则引起的性能损失将使应用程序的性能得不偿失。  
              GC   垃圾自动回收算法本身是相当合理的。除非程序员确认真有必要,才调用此方法。Top

2 楼AntingZ(夕惕若)回复于 2004-08-02 21:16:25 得分 12

markTop

3 楼lzmtw(水如烟)回复于 2004-08-02 21:22:51 得分 2

学习Top

4 楼lzmtw(水如烟)回复于 2004-08-02 21:23:13 得分 12

可惜一点不懂,要不可以说两句Top

5 楼NEODIO(阿迪)回复于 2004-08-02 21:48:52 得分 12

VB.NET中没有析构函数吗?Top

6 楼AntingZ(夕惕若)回复于 2004-08-02 21:48:56 得分 12

A的实例close后,其成员变量clsB(classB的一个实例)的生命周期也就结束了,  
  即使不在析构函数里面执行clsB=nothing;   GC也能检测到clsB在作为A的成员变量  
  这种关系不存在了,在适当的时候可以回收,  
  至于该不该回收,还要看有没有其他地方引用这个clsB.  
  就算你在析构函数里面用了clsB=Nothing;   GC也并不认为clsB是可以立刻回收的对象,它还是  
  要检测有没有其他地方引用了这个clsB。如果没有了才可以回收。  
  所以写不写clsB=nothnig都无所谓。(写的话是不是可以加快GC检测的时间?不是很清楚)  
  ----------------------------  
  以上是目前脑海中的印象,不知道是对还是错的,再查查资料看看  
  Top

7 楼AntingZ(夕惕若)回复于 2004-08-02 21:54:55 得分 12

public   class   A  
  {  
        classB   clsB   =   new   classB();...  
   
        public   A()  
        {  
          }  
        ~public   A()  
        {  
              clsB   =   null;  
        }  
        public   setb()  
        {  
            g_clsB=clsB;//假设g_clsB是定义的一个全局变量(ClassB类型)  
        }  
  }  
   
  那么调用setB()后,即使在析构函数中调用了clsB   =   null;   GC还是不能回收clsB   .  
  如果你现在就回收clsB的话,那么在其他地方引用g_clsB的话,岂不会出错?Top

8 楼AntingZ(夕惕若)回复于 2004-08-02 22:15:36 得分 12

gc会维护每个对象的引用情况:  
  比如  
   
  dim   a   as   new   A()  
  //同时构造了一个clsB   [classB   clsB   =   new   classB();]  
  //gc记住了clsB在a里面引用着【一个引用】  
   
  a.setb()  
  //gc记住了clsB又被g_clsB引用了,那么引用次数加1,现在就变成【两个引用】  
   
  a.close()  
  //调用   ~public   A()中的clsB   =   null;  
  //gc要吧clsB的引用次数减少一次,发现原来是被应用了两次,现在变成了【一个引用】  
  //即使你不显示的调用clsb=null;gc也会检测出来,然后减少一次引用。  
  //所以现在GC发现clsB还有引用,所以不能回收  
   
  //如果你现在在某个地方这样  
  dim   tb   as   new   classB();  
  g_clsB=tb;  
  //g_clsB现在指向tb.那么原来的指向(clsB)就要减少一次了,以前是1,所以现在是【零个引用】  
  //好了现在clsB的应用次数成0了,说明真的没用了,  
  //等到gc来回收的时候,就可以释放clsB占用的内存了.  
   
   
  //当然如果你中途没有调用a.setB(),那么a.close()之后clsB的引用次数就是0了,  
  //gc就认为是可以回收的了  
   
   
  -----------------------------------------  
  我记得是当时学.net的时候我们老师这样讲的,不知道他讲错了没有,也不知道我记错了没有  
   
  欢迎大家批评指正!  
   
   
  Top

9 楼liyiding23(代码人生)回复于 2004-08-02 22:21:21 得分 2

GZTop

10 楼terryxin(南方窗口)回复于 2004-08-03 08:30:14 得分 0

upTop

11 楼wnlovezxm(大垃圾人)回复于 2004-08-03 08:48:55 得分 2

没有析构,不用考虑内存溢出,你做的是应用系统,你考虑的应该是完善需求,挖掘需求!Top

12 楼qjoe0516(心雨)回复于 2004-08-03 08:57:56 得分 2

学习Top

13 楼dai2003(天剑)回复于 2004-08-03 09:03:47 得分 2

這樣改一下代碼看行不行  
  Dim   frm2   As   Object  
      frm2   =   New   Form2()  
      frm2.Show()  
      Me.Enabled   =   False  
      me.close()Top

14 楼terryxin(南方窗口)回复于 2004-08-03 10:25:47 得分 0

老大,现在不是遇到问题才解决的吗?两个窗口切换如果数据量很大的话,吃内存比较厉害,如果不能及时的释放的话,可能导致系统崩溃Top

15 楼terryxin(南方窗口)回复于 2004-08-03 15:02:50 得分 0

高手们来谈谈啊Top

16 楼terryxin(南方窗口)回复于 2004-08-04 09:18:22 得分 0

这几天这边的人气真的很差啊,高手都不哪儿了啊Top

17 楼webmasterss(天涯解语花)回复于 2004-08-11 23:37:32 得分 2

我是超级菜鸟,什么叫vb.net啊?煮着吃还是清蒸吃?Top

18 楼jiemupig(伦涯飘)回复于 2004-08-12 01:24:44 得分 3

呵。清蒸吃!Top

19 楼yzg100(100学编程)回复于 2004-08-13 09:01:14 得分 4

学习。Top

20 楼strXiaoCaiNiao(兰冰)回复于 2004-08-13 09:12:33 得分 5

I   don't   know   ,UPTop

21 楼wqhzjl(忠秋不悔)回复于 2004-08-13 09:17:28 得分 6

学习Top

22 楼avon520(阿云)回复于 2004-08-13 09:24:22 得分 0

好  
  UPTop

23 楼yingshis(英石)回复于 2004-08-13 11:18:42 得分 6

说不好  
  一起研究吧Top

24 楼terryxin(南方窗口)回复于 2004-08-16 14:41:43 得分 0

看来真的没有这方面的高手Top

25 楼ShintaX(蓝天起,黄龙现,一灯初烛千年不灭)回复于 2004-08-16 15:29:58 得分 6

我在改进,有成果了,嘿嘿,等我过一下贴上来。Top

26 楼terryxin(南方窗口)回复于 2004-08-16 15:41:45 得分 0

好的,谢谢Top

27 楼islkeng(A仔)回复于 2004-08-16 16:41:36 得分 6

请试一试:  
  Dim   frm2   As   Object  
      frm2   =   New   Form2()  
      frm2.ShowDialog()  
      Me.Hide()  
      Me.Enabled   =   False  
      me.Dispose()Top

28 楼liyiding23(代码人生)回复于 2004-08-16 16:50:14 得分 18

Public   Sub   New()  
   
                  MyBase.New()  
   
          End   Sub  
   
          Protected   Overloads   Overrides   Sub   Dispose(ByVal   disposing   As   Boolean)  
   
                  If   disposing   Then  
   
                          If   Not   (components   Is   Nothing)   Then  
   
                                  components.Dispose()  
   
                          End   If  
   
                  End   If  
   
                  MyBase.Dispose(disposing)  
   
          End   Sub  
     
   
  MyBase   关键字的行为类似于引用类的当前实例的基类的对象变量。MyBase   常用于访问在派生类中被重写或隐藏的基类成员。在这段代码中,MyBase指的当然就是System.Windows.Forms.Form类了。构造对象时用的New方法是显式调用的Form.Dispose方法是重写自Control.Dispose方法的,那么Control.Dispose方法的含义又是怎么样的?它的作用就是:释放由Control占用的非托管资源,还可以另外再释放托管资源。当它参数中的disposing   为   true   则释放托管资源和非托管资源;为   false   则仅释放非托管资源。   Form类的disposing为true。在关闭窗体时自动调用dispose的功能是得益于.net的公共语言运行库,运行库自动处理对象布局和管理对对象的引用,当不再使用对象时释放它们。其生存期以这种方式来管理的对象称为托管数据。自动内存管理消除了内存泄漏以及其他一些常见的编程错误。任何类型的   Dispose   方法都应该释放它拥有的所有资源。它还应该通过调用其父类型的   Dispose   方法释放其基类型拥有的所有资源。该父类型的   Dispose   方法应该释放它拥有的所有资源并同样也调用其父类型的   Dispose   方法,从而在整个基类型层次结构中传播该模式。要确保始终正确地清理资源,Dispose   方法应该可以被多次安全调用而不引发任何异常可是,如果系统问题或应用程序调用上出了问题,不能正常调用Dispose怎么办如果通过Dispose还释放不干净或没有调用Dispose,系统的垃圾回收器会调用对象的   Finalize   方法进行清除。由于执行   Finalize   方法会大大减损性能,所以我们不会一开始就用它去进行清除工作Top

29 楼terryxin(南方窗口)回复于 2004-08-17 00:42:53 得分 0

好的尝试一下,谢谢  
  Top

30 楼strXiaoCaiNiao(兰冰)回复于 2004-08-17 08:57:54 得分 2

学习,UPTop

31 楼webmasterss(天涯解语花)回复于 2004-08-17 14:44:28 得分 2

up,期待更多高手参与!Top

32 楼terryxin(南方窗口)回复于 2004-08-18 10:17:36 得分 0

是啊Top

33 楼weiljj()回复于 2004-08-18 10:48:23 得分 2

靠,學.NET還有老師教,真爽.Top

34 楼swiminfish(纸飞机)回复于 2004-08-24 13:43:42 得分 2

帮你   up     有空就做做好事,逞点分   ,呵呵  
  Top

35 楼Night_Elf(风暴虫)回复于 2004-08-24 13:48:20 得分 2

学习中!Top

36 楼CrazyKyro(CrazyKyro)回复于 2004-08-24 14:30:37 得分 2

如果一个对象的引用次数为0,垃圾回收器就可以释放该对象所占的资源,但无法保证何时释放。  
   
  可以显式调用System.GC.Collect()来要求运行垃圾回收器。  
   
  但不推荐这样做,频繁地使用System.GC.Collect()会大大降低效率。  
   
  个人的看法,大家指正   ...Top

37 楼dai2003(天剑)回复于 2004-08-24 14:54:03 得分 2

呵,呵,對內存的管理現在了解的不多,不過我覺得這樣寫可能會好一點:  
      Dim   frm2   As   Object  
      frm2   =   New   Form2()  
      frm2.Show()  
      me.close()  
  Top

38 楼viber(大概知道)回复于 2004-08-24 15:22:48 得分 2

觉得代码人生的方法行,判断是否释放,没释放就给内存释放掉,Top

39 楼allen1981813(Nahe des Geliebten)回复于 2004-08-24 15:25:12 得分 2

既然是.NET平台了,考虑那么多干吗?  
  Top

40 楼sxbcsdn(石破)回复于 2004-08-24 16:23:08 得分 2

嗯,有道理。我再消化一下。Top

41 楼Night_Elf(风暴虫)回复于 2004-08-24 19:56:47 得分 2

那请问在Form2中怎么把Form1关掉呀,而form2并不关闭!Top

42 楼ShintaX(蓝天起,黄龙现,一灯初烛千年不灭)回复于 2004-08-25 08:26:49 得分 2

内存溢出在你这里不用考虑。涉及不到的。Top

43 楼youlongzaitian(游龙在天)回复于 2004-08-25 08:58:07 得分 2

通过FORM1中的事件来触发显示FORM2,同时将FORM1中的数据传到FORM2,并且关闭PORM1,现在碰到传数据并关闭FORM1就出错,有哪位遇到过这样的问题呀?请指教指教!Top

44 楼wangdequan1024(紫夜)回复于 2004-09-22 09:03:48 得分 2

winform不熟,帮顶Top

45 楼lcge(沙漠)回复于 2004-09-22 09:32:28 得分 2

ding...Top

46 楼yikais(红树林)回复于 2004-09-22 09:53:13 得分 2

帮楼主顶,值得关注!!!Top

47 楼liujiayu10(活着就好)回复于 2004-09-22 10:49:59 得分 2

我想主要是讨论:close与dispose吧  
  我只用CloseTop

48 楼wuzd(兀)回复于 2004-09-22 15:41:35 得分 2

有道道Top

49 楼haoztao(.NET一族)回复于 2004-09-22 16:04:12 得分 2

可以使用接口函数去释放内存用IDisposableTop

50 楼gzy11(可可猫)回复于 2004-09-22 21:24:36 得分 2

好帖值得学习~Top

51 楼weige250(桂电weige)回复于 2004-09-23 00:50:20 得分 2

learnTop

52 楼NULLvalue(另类)回复于 2004-09-23 07:56:30 得分 2

mark&upTop

53 楼hhhh63(hhhh63)回复于 2004-09-23 08:52:49 得分 2

terryxin(有聊的冬季)   说的很深,有点象过去编C++程序时的内存管理方法一样,内存的分配和释放全由程序员控制。开始做.net程序时很不习惯,只有new,没有release,后来才知道.net自动管理内存,不用人为释放。MSDN中有比较通俗详细的说明,叫拉圾回收。  
   
  总的来说,vb.net和c#.net会自动管理内存(非托管代码除外,一般也很少用到),正常情况下,长时间连续运行,内存消耗不会增加。不过实际使用时,也有一些内存管理技巧。  
   
  尽量减少对象的生成周期,也就是说多用局部变量(在函数是定义),少用类变量(在类中定义),尽量不用静态变量。  
   
  很多朋友在回答问题时都说用静态变量,如类与类之间的变量传递问题,多数都说用静态变量。这是一种很不好的方法,静态变量会一直占有内存,更重要的是这种用法违背了.net的基本原则。Top

54 楼xuxun(我思故我在)回复于 2004-09-23 09:17:43 得分 2

试的结果怎么样呀,有没有什么说法?Top

55 楼echo123321(今年过年不回家)回复于 2004-09-23 09:22:40 得分 2

学Top

56 楼micropentium6(小笨|曾经的美好)回复于 2004-09-23 10:37:44 得分 2

同意liyiding23(代码人生)的看法,内存、资源清理(指form2中成员变量的内存和资源)应该在dispose方法中完成;楼主在一楼的帖子让我想起以前看书时的一个疑问:  
   
  GC只会collect实现finalize方法的类实例内存,而实现dispose方法的类可以不实现finalize方法。换句话说,这样的类实例将会在其超出变量作用域时被立即回收?就象楼主说的第2代,会随着下次collect的发生被马上回收。  
   
  那么存在这样的只实现dispose而不实现finalize的类吗?我找到所有引用类型的基类object的实现,在里面我找到一个空的finalize方法,也就是说至少在引用类型里似乎不存在这样的类。  
   
  如果想立即回收内存,可以试试这样:  
  GC.Collect();            
  GC.WaitForPendingFinalizers();  
  GC.Collect();  
  第一遍回收collect,会强制GC检查FReachable(模糊记得表叫这个:)中对象的finalize方法并调用,然后WaitForPendingFinalizers等待调用析构函数结束,最后再次collect,回收内存。  
   
  但是,如果:  
   
  Form2   frm2=new   Form2();  
  //frm2.Show();  
  frm2=null;  
   
  GC.Collect();  
  GC.WaitForPendingFinalizers();  
  GC.Collect();  
   
  这时你会发现form2的finalize和dispose被先后调用了,这是因为在form的基类中,finalize方法就是调用dispose(),而dispose()调用dispose(true)并SuppressFinalize,资源回收将在dispose(bool)中进行。  
   
  但如果去掉上面代码我注释掉的部分,GC将不会回收fomr2内存,表面上看,我只有一个引用指向form2的这个实例,并且我已经frm2=null;但实际上,可以肯定的是,当调用show方法时,又至少有一个引用指向了这个实例,所以当此时对form2实例进行collect时,GC会发现仍然有根指向它,所以不会对它采取行动。  
   
  如果楼主的程序只是要在两个窗体间不断切换,何不试试弱引用?weakreference,也许会对你有所帮助,但它何内存回收无关:)Top

57 楼tl_pear(飘叶寻梦)回复于 2004-09-23 10:43:05 得分 2

在VB.net中是没有析构函数的,它是通过GC来进行管理的。CLS跟踪拖管堆中的对象,当应用程序不再需要时就释放这些对象,使得对对象的管理变得简单,但是也就是因为它对对象释放的不确定性,不能确定结束代码在什么时候运行。  
  VB.net中提供了一个接口IDisposable,它的方法Dispose是.NET   Framework提供的一个处理对象的替代方法。通过编写Dispose方法,在方法中调用GC.SuppressFinalize(),来对对象进行处理!Top

58 楼dofly(巴山夜雨)回复于 2004-09-23 10:45:58 得分 2

学习。。。。  
   
  等空闲的时候来研究Top

59 楼tl_pear(飘叶寻梦)回复于 2004-09-23 10:50:06 得分 2

补充一下:Finalize()和Dispose()方法,前者是隐式的对对象的处理,对程序员通明的,不知道什么时候会对对象处理,后者可以显示的调用,并通过编码,可以及时的对对象进行处理!Top

60 楼micropentium6(小笨|曾经的美好)回复于 2004-09-23 10:58:12 得分 2

to   tl_pear(飘叶寻梦):  
  ”在方法中调用GC.SuppressFinalize(),来对对象进行处理!“  
   
  调用SuppressFinalize()的目的是什么,它如何处理对象?:)  
   
  顾名思义,它的目的是在调用dispose方法执行完清理后,防止finalize方法被再次调用Top

61 楼tl_pear(飘叶寻梦)回复于 2004-09-23 11:39:34 得分 2

不好意思!  
  谢谢   micropentium6(小笨|想学ASP)   的指正!  
  GC.SuppressFinalize()的目的是防止finalize方法被再次调用  
  由于语意不明确,导致理解有误,其实我的意思是重点是通过对Dispose方法编码,  
  而不是要通过GC.SuppressFinalize()这个方法来达到对对象处理的要求!  
  其实我的意思只是想说:可以通过使用Dispose来实现及时对对象的处理!Top

相关问题

  • 如何从内存中释放窗体??
  • MDI中子窗体的内存释放问题(菜鸟问题)
  • 提问:卸载窗体为什么不能释放内存
  • 请问模式窗体的ModalResult=mrOK,窗体关闭后是否已经从内存中释放?
  • 怎样做才能实现点击按钮动态生成一个窗体,关闭窗体后,同时释放内存。
  • 请问在将窗体的FormBorderstyle属性设置为None后如何定时释放窗体所占内存(类似最小化事件)?
  • 如何用代码实现窗体最小化时那样的释放内存(把内存的东西写入虚拟内存?)?
  • Form窗体关闭了,但是应用程序内存未释放,怎么办(在线等待,马上给分)
  • 如何实现退出窗体时释放ADODC数据库连接占有的内存资源?
  • 请教eVB中释放单个窗体内存的问题那位有好的解决方法。

关键词

  • .net
  • vb.net
  • 内存
  • 函数
  • 垃圾
  • 管理
  • 算法
  • 程序员
  • 代码
  • clsb

得分解答快速导航

  • 帖主:terryxin
  • AntingZ
  • lzmtw
  • lzmtw
  • NEODIO
  • AntingZ
  • AntingZ
  • AntingZ
  • liyiding23
  • wnlovezxm
  • qjoe0516
  • dai2003
  • webmasterss
  • jiemupig
  • yzg100
  • strXiaoCaiNiao
  • wqhzjl
  • yingshis
  • ShintaX
  • islkeng
  • liyiding23
  • strXiaoCaiNiao
  • webmasterss
  • weiljj
  • swiminfish
  • Night_Elf
  • CrazyKyro
  • dai2003
  • viber
  • allen1981813
  • sxbcsdn
  • Night_Elf
  • ShintaX
  • youlongzaitian
  • wangdequan1024
  • lcge
  • yikais
  • liujiayu10
  • wuzd
  • haoztao
  • gzy11
  • weige250
  • NULLvalue
  • hhhh63
  • xuxun
  • echo123321
  • micropentium6
  • tl_pear
  • dofly
  • tl_pear
  • micropentium6
  • tl_pear

相关链接

  • CSDN .NET频道
  • .NET类图书
  • C#类图书
  • .NET类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
世纪乐知(北京)网络技术有限公司 版权所有, 京 ICP 证 020026 号
北京创新乐知广告有限公司 提供技术支持
Copyright © 2000-2007, CSDN.NET, All Rights Reserved
GongshangLogo