[英]C# - Preparing An Object For GC Before Calling GC.Collect
Thanks 谢谢
Thanks for all the comments and answers, it seems that everyone shares the same opinion. 感谢您的所有评论和回答,似乎每个人都有相同的看法。
As long as nothing else can see the object it is already eligible for collection; 只要没有其他东西可以看到该对象 ,则该对象已经可以收集。 nothing more is required.
不再需要。 The key point here is to ensure that nothing else is watching it (or at least, nothing with a longer lifetime):
这里的关键点是确保没有其他人在看它(或者至少没有任何人有更长的寿命):
I genuinely doubt that GC.Collect()
is the answer here; 我真的怀疑
GC.Collect()
是这里的答案。 if it was eligible it would have already been collected. 如果符合条件,它将已经被收集。 If it isn't elgible, calling
GC.Collect()
certainly won't help and quite possibly will make things worse (by tying up CPU when nothing useful can be collected). 如果不是 elgible,调用
GC.Collect()
当然不会帮助,很可能会让事情变得更糟(由占用CPU没事的时候非常有用,可以收集)。
You don't generally need to do anything. 您通常不需要执行任何操作。
If the object is no longer referenced then it's a candidate for collection. 如果该对象不再被引用,则它是一个候选集合。 (And, conversely, if the object is still referenced then it's not a candidate for collection, however you "prepare" it.)
(相反,如果仍引用该对象,则该对象不是收集对象,但是您可以“准备”该对象。)
You need to clean up any unmanaged resources like database connections etc. 您需要清理所有非托管资源,例如数据库连接等。
Typically by implementing IDisposable
and call Dispose
. 通常通过实现
IDisposable
并调用Dispose
。
If you have a finalizer you should call GC.SuppressFinilize
. 如果您有终结器,则应致电
GC.SuppressFinilize
。
The rest is cleaned up by the garbage collector. 其余的由垃圾收集器清理。
Edit: 编辑:
And, oh, naturally you need to release all references to your object. 而且,哦,自然地,您需要释放对对象的所有引用。
But , and here is this big but. 但是 ,这是很大的。 Unless you have a very very special case you don't need to call GC.Collect.
除非您有非常特殊的情况,否则不需要调用GC.Collect。 You probably forgets to release some resources or references, and GC.Collect won't help you with that.
您可能会忘记释放一些资源或参考,而GC.Collect将无法为您提供帮助。 Make sure you call
Dispose
on everything Disposable (preferably with the using-pattern). 确保对所有Disposable(最好使用using模式)调用
Dispose
。
You should probably pick up a memory profiler like Ants memory profiler and look where all your memory has gone. 您可能应该选择像Ants内存探查器这样的内存探查器,并查看所有内存都去了哪里。
If you have no more direct reference to an object, and you're running out of memory, GC should do this automatically. 如果没有更多直接引用对象,并且内存不足,GC应该自动执行此操作。 Do make sure you call .Dispose() on your datacontext.
确保确保在数据上下文上调用.Dispose()。
Calling GC.Collect
will hardly ever prevent you from getting OutOfMemory exceptions, because .NET will call GC.Collect
itself when it is unable to create a new object due to OOM. 调用
GC.Collect
几乎不会阻止您获得OutOfMemory异常,因为.NET因OOM而无法创建新对象时,它将调用GC.Collect
本身。 There is only one scenario where I can think of and that is when you have unreferenced objects that are registered in the finalizable queue. 我只能想到一种情况,那就是当您在未终结的队列中注册了未引用的对象时。 When these objects reference many other objects it can cause a OOM.
当这些对象引用许多其他对象时,可能会导致OOM。 The solution to this problem is actually not to call
GC.Collect
but to ensure that those objects are disposed correctly (and implement the dispose pattern correctly when you created those objects). 解决此问题的方法实际上不是调用
GC.Collect
而是确保正确放置了这些对象(并在创建这些对象时正确地实现了放置模式)。
Using GC.Collect in general 一般使用GC.Collect
Since you are trying to get rid of a very large collection, it's totally valid to use GC.Collect(). 由于您试图摆脱一个非常大的集合,因此使用GC.Collect()是完全有效的。 From the Microsoft docs :
从Microsoft文档 :
... since your application knows more about its behavior than the runtime does, you could help matters by explicitly forcing some collections.
...由于您的应用程序比运行时更了解其行为,因此可以通过显式强制某些集合来帮助解决问题。 For example, it might make sense for your application to force a full collection of all generations after the user saves his data file.
例如,在用户保存数据文件之后,强制应用程序的所有世代都可能对您的应用程序有意义。
"Preparing" your objects “准备”您的对象
From the excellent Performance Considerations for Run-Time Technologies in the .NET Framework (from MSDN): 从.NET Framework中的运行时技术出色的性能考虑 (来自MSDN):
If you keep a pointer to a resource around, the GC has no way of knowing if you intend to use it in the future.
如果您保持指向资源的指针,则GC无法知道您将来是否打算使用它。 What this means is that all of the rules you've used in native code for explicitly freeing objects still apply, but most of the time the GC will handle everything for you.
这意味着您在本机代码中用于显式释放对象的所有规则仍然适用,但是大多数情况下,GC会为您处理所有事情。
So, to ensure it's ready for GC, Make sure that you have no references to the objects you wish to collect (eg in collections, events, etc...). 因此,要确保已准备好将其用于GC,请确保您没有对要收集的对象的引用(例如,在收集,事件等中)。 Setting the variable to null will mean it's ready for collection before the variable goes out of scope.
将变量设置为null意味着在变量超出范围之前可以进行收集。
Also any object which implements IDisposable should have it's Dispose() method called to clean up unmanaged resources. 同样,任何实现IDisposable的对象都应调用其Dispose()方法来清理非托管资源。
Before you use GC.Collect 使用GC.Collect之前
Since it looks like your application is a server, using the Server GC may resolve your issue. 由于您的应用程序看起来像是服务器,因此使用Server GC可能会解决您的问题。 It will likely run more often and be more performant in a multi-processor scenario.
在多处理器方案中,它可能会更频繁地运行并且性能更高。
The server GC is designed for maximum throughput, and scales with very high performance.
服务器GC旨在实现最大吞吐量,并具有很高的性能进行扩展。
See the Choosing Which Garbage Collector to Use within Performance Considerations for Run-Time Technologies in the .NET Framework (from MSDN): 请参阅在.NET Framework中从运行时技术的性能考虑因素中 选择使用哪个垃圾收集器 (来自MSDN):
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.