精华帖 (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()函数,不知道有什么解决的办法? 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2005-08-08
我知道这里基本都是JAVA的高手,但我想NET的高手也应该潜伏在这里,能不能给个较好的解决方案,或者指出我的问题是什么。谢谢。
|
|
返回顶楼 | |
发表时间:2005-08-10
使用链表怎么会导致内存不能自动回收?
|
|
返回顶楼 | |
发表时间: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();去掉看看效果. 不过内存回收速度非常的慢,一定会影响程序效率.建议少用,而是设法优化你的代码. |
|
返回顶楼 | |
发表时间:2005-08-13
GC.Collect() 和GC.WaitForPendingFinalizers() 不是马上就执行的,framework 会把请求放到一个thread 里去做, 关键是要保证你的instance没有被reference, 对于大的对象, 可以在用完后call SuppressFinalize.
System.GC.SuppressFinalize(instance_object); |
|
返回顶楼 | |
发表时间:2005-08-15
谢谢各位的回复.
|
|
返回顶楼 | |
发表时间: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();去掉看看效果. 不过内存回收速度非常的慢,一定会影响程序效率.建议少用,而是设法优化你的代码. 如何建立内存对象池? |
|
返回顶楼 | |
发表时间: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发布。 |
|
返回顶楼 | |
发表时间:2005-08-19
http://msdn.microsoft.com/msdnmag/issues/05/01/MemoryOptimization/default.aspx
|
|
返回顶楼 | |
发表时间:2005-08-19
如果你需要用到GC.Collect(),基本上可以认为应该优化代码结构。
在具体应用一般应该避免这种麻烦事,毕竟MSDN的关于GC的demo都是理论性质的,实践过程中要复杂的多。 |
|
返回顶楼 | |