论坛首页 编程语言技术论坛

『提问』.net如何在windows服务程序中回收内存

浏览 13319 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2005-08-08  
软件环境:
win2000+.net2003+C#
我建立了一个服务项目,由于程序中频繁的使用链表IList导致内存不能自动回收。因此我采用了
	GC.Collect();;
			GC.WaitForPendingFinalizers();;
			GC.Collect();;

来回收内存。在控制台方式下没有任何问题,内存被回收了并且程序运行正常。但是在服务方式下OnStart这个线程会被挂起,导致程序不能运行。
配置文件:

错误提示信息:
在服务方式下OnStart这个线程会被挂起,导致程序不能运行。
你的分析:
我认为WaitForPendingFinalizers函数会挂起任何线程去回收内存,但是不会挂起主线程即main();有于.net下会收内存是非常模糊的。我看过很多资料,没有什么人能说清楚。并且手动回收内存的方式只有显示的调用GC。所以我不知道这个是不是.net里面的一个问题,不能在服务程序中调用WaitForPendingFinalizers()函数,不知道有什么解决的办法?
   发表时间:2005-08-08  
我知道这里基本都是JAVA的高手,但我想NET的高手也应该潜伏在这里,能不能给个较好的解决方案,或者指出我的问题是什么。谢谢。
0 请登录后投票
   发表时间:2005-08-10  
使用链表怎么会导致内存不能自动回收?
0 请登录后投票
   发表时间:2005-08-12  
loatee 写道
软件环境:
win2000+.net2003+C#
我建立了一个服务项目,由于程序中频繁的使用链表IList导致内存不能自动回收。因此我采用了
	GC.Collect();;
			GC.WaitForPendingFinalizers();;
			GC.Collect();;

来回收内存。在控制台方式下没有任何问题,内存被回收了并且程序运行正常。但是在服务方式下OnStart这个线程会被挂起,导致程序不能运行。
配置文件:

错误提示信息:
在服务方式下OnStart这个线程会被挂起,导致程序不能运行。
你的分析:
我认为WaitForPendingFinalizers函数会挂起任何线程去回收内存,但是不会挂起主线程即main();有于.net下会收内存是非常模糊的。我看过很多资料,没有什么人能说清楚。并且手动回收内存的方式只有显示的调用GC。所以我不知道这个是不是.net里面的一个问题,不能在服务程序中调用WaitForPendingFinalizers()函数,不知道有什么解决的办法?


就算是.net程序,如果是超长时间运行的代码,也要自己建立内存对象池.不然再多的内存,也有内存不够的时候.
而且内存回收的基本条件之一是,你不在任何地方引用对象,这样在内存对象引用计数器为0之后,就会放入内存回收队列中去. 具体的方法是object = null,明确告诉系统,object我不用了.

同时如果你的每一个对象都是大内存对象的话,那么程序效率就会降低.
另外建议你 GC.WaitForPendingFinalizers();去掉看看效果. 不过内存回收速度非常的慢,一定会影响程序效率.建议少用,而是设法优化你的代码.
0 请登录后投票
   发表时间:2005-08-13  
GC.Collect() 和GC.WaitForPendingFinalizers() 不是马上就执行的,framework 会把请求放到一个thread 里去做, 关键是要保证你的instance没有被reference, 对于大的对象, 可以在用完后call SuppressFinalize.

System.GC.SuppressFinalize(instance_object);
0 请登录后投票
   发表时间:2005-08-15  
谢谢各位的回复.
0 请登录后投票
   发表时间:2005-08-19  
jack 写道
loatee 写道
软件环境:
win2000+.net2003+C#
我建立了一个服务项目,由于程序中频繁的使用链表IList导致内存不能自动回收。因此我采用了
	GC.Collect();;
			GC.WaitForPendingFinalizers();;
			GC.Collect();;

来回收内存。在控制台方式下没有任何问题,内存被回收了并且程序运行正常。但是在服务方式下OnStart这个线程会被挂起,导致程序不能运行。
配置文件:

错误提示信息:
在服务方式下OnStart这个线程会被挂起,导致程序不能运行。
你的分析:
我认为WaitForPendingFinalizers函数会挂起任何线程去回收内存,但是不会挂起主线程即main();有于.net下会收内存是非常模糊的。我看过很多资料,没有什么人能说清楚。并且手动回收内存的方式只有显示的调用GC。所以我不知道这个是不是.net里面的一个问题,不能在服务程序中调用WaitForPendingFinalizers()函数,不知道有什么解决的办法?


就算是.net程序,如果是超长时间运行的代码,也要自己建立内存对象池.不然再多的内存,也有内存不够的时候.
而且内存回收的基本条件之一是,你不在任何地方引用对象,这样在内存对象引用计数器为0之后,就会放入内存回收队列中去. 具体的方法是object = null,明确告诉系统,object我不用了.

同时如果你的每一个对象都是大内存对象的话,那么程序效率就会降低.
另外建议你 GC.WaitForPendingFinalizers();去掉看看效果. 不过内存回收速度非常的慢,一定会影响程序效率.建议少用,而是设法优化你的代码.


如何建立内存对象池?
0 请登录后投票
   发表时间:2005-08-19  
实际上,.net CLR对垃圾回收采用的是代龄(generation)机制,也就是GC.Collect()或者GC.WaitForPendingFinalizers()并不一定会立即触发完整的垃圾回收操作的(尤其是对代龄>1的)。而且,使用WaitForPendingFinalizers会挂起线程,在服务程序中使用存在风险。

这问题得看具体情况,一般来说:
1、如果用到非托管资源,那么采用Dispose模式;
2、不要使用长弱引用,比如IList成员变量,一旦对象代龄增加到2,那基本上它就赖着了;
3、尽量不要使用GC.Collect(),CLR有自己的算法来处理,它未必听你的;
4、如果在线程中使用GC.Collect()或者导致了垃圾收集的执行,那么其他线程不能访问任何对象,CLR会挂起所有已经执行到临界区的线程,然后进行安全点识别,同时进行对象搬迁,呵呵,麻烦死人的,会很耗时,尽量避免。

还有,好像Debug版本的Assembly会阻止Garbage Collect,改用Release发布。
0 请登录后投票
   发表时间:2005-08-19  
http://msdn.microsoft.com/msdnmag/issues/05/01/MemoryOptimization/default.aspx
0 请登录后投票
   发表时间:2005-08-19  
如果你需要用到GC.Collect(),基本上可以认为应该优化代码结构。
在具体应用一般应该避免这种麻烦事,毕竟MSDN的关于GC的demo都是理论性质的,实践过程中要复杂的多。
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics