由于
感谢所有的评论和回答,似乎每个人都持有同样的观点。
答案 0 :(得分:3)
只要没有其他任何东西可以看到对象,它就已经有资格收集;没有必要。这里的关键是确保没有其他东西正在观看它(或者至少没有其他东西在观看它):
我真的怀疑GC.Collect()
是这里的答案;如果它符合条件,它就已经被收集了。如果不是可以识别,那么调用GC.Collect()
肯定无济于事,很可能会使事情变得更糟(通过在没有任何有用的东西时收集CPU)。
答案 1 :(得分:2)
您通常不需要做任何事情。
如果不再引用该对象,则它是收集的候选对象。 (相反,如果对象仍被引用,则它不是收集的候选者,但是你“准备”它。)
答案 2 :(得分:1)
您需要清理任何非托管资源,如数据库连接等。
通常是通过实施IDisposable
并致电Dispose
。
如果您有终结器,请拨打GC.SuppressFinilize
。
其余部分由垃圾收集器清理。
修改强>
而且,哦,当然你需要释放对象的所有引用。
但是,这是一个很大但是。除非你有一个非常特殊的情况,否则你不需要调用GC.Collect。您可能忘记释放一些资源或引用,GC.Collect将无法帮助您。确保在所有Disposable上调用Dispose
(最好使用使用模式)。
你应该选择一个像Ants memory profiler这样的内存分析器,看看你的所有内存消失了。
答案 3 :(得分:1)
如果您没有对某个对象的更直接引用,并且内存不足,GC应该自动执行此操作。确保在datacontext上调用.Dispose()。
答案 4 :(得分:1)
调用GC.Collect
几乎不会阻止您获取OutOfMemory异常,因为当由于OOM而无法创建新对象时,.NET将调用GC.Collect
。我只能想到一个场景,那就是当你有可以在可终结队列中注册的未引用对象时。当这些对象引用许多其他对象时,它可能会导致OOM。这个问题的解决方案实际上不是调用GC.Collect
,而是确保正确放置这些对象(并在创建这些对象时正确实现dispose模式)。
答案 5 :(得分:1)
一般使用GC.Collect
因为你试图摆脱一个非常大的集合,所以使用GC.Collect()是完全有效的。来自Microsoft docs:
...因为您的应用程序比运行时更了解其行为,所以您可以通过显式强制某些集合来帮助解决问题。例如,您的应用程序在用户保存其数据文件后强制完整收集所有代数可能是有意义的。
“准备”您的对象
来自优秀的Performance Considerations for Run-Time Technologies in the .NET Framework(来自MSDN):
如果您保留指向资源的指针,GC无法知道您是否打算将来使用它。这意味着您在本机代码中用于显式释放对象的所有规则仍然适用,但大多数情况下GC将为您处理所有内容。
因此,为了确保它已准备好用于GC,请确保您没有对要收集的对象的引用(例如,在集合,事件等中)。将变量设置为null意味着在变量超出范围之前它已准备好进行收集。
任何实现IDisposable的对象都应该调用它的Dispose()方法来清理非托管资源。
使用GC.Collect之前
由于您的应用程序看起来像是服务器,因此使用Server GC可能会解决您的问题。在多处理器场景中,它可能会更频繁地运行并且性能更高。
服务器GC旨在实现最大吞吐量,并以非常高的性能进行扩展。
在Performance Considerations for Run-Time Technologies in the .NET Framework(来自MSDN)中查看选择要使用的垃圾收集器: