C#-在调用GC.Collect之前为GC准备对象 脚本 假设我已经决定我真的需要调用GC.Collect() 在实际调用此方法之前,我需要做什么来确保对象已准备好进行适当的垃圾收集 将null分配给对象的所有属性就足够了吗?或者只是给对象本身赋值null 如果你真的需要知道为什么。。。。。 我在WCF中有一个分布式应用程序,它每隔几秒钟通过网络发送一个DataContract,其中包含8个字典作为DataMember 这是大量的数据,当它进入客户端接口时,会创建一个全新的DataContract对象,并且应用程序的内存使用量增长如此之大,以至于我无法避免内存异常

C#-在调用GC.Collect之前为GC准备对象 脚本 假设我已经决定我真的需要调用GC.Collect() 在实际调用此方法之前,我需要做什么来确保对象已准备好进行适当的垃圾收集 将null分配给对象的所有属性就足够了吗?或者只是给对象本身赋值null 如果你真的需要知道为什么。。。。。 我在WCF中有一个分布式应用程序,它每隔几秒钟通过网络发送一个DataContract,其中包含8个字典作为DataMember 这是大量的数据,当它进入客户端接口时,会创建一个全新的DataContract对象,并且应用程序的内存使用量增长如此之大,以至于我无法避免内存异常,c#,garbage-collection,C#,Garbage Collection,谢谢 编辑 感谢所有的评论和回答,似乎每个人都有相同的观点 我无法理解的是,由于连接一直处于打开状态,我如何才能正确处理 一旦我从传入对象复制了数据,我就不再需要该对象了,那么在DataContract对象上实现IDisposable就足够了吗 我最初的问题是- 您通常不需要做任何事情 如果对象不再被引用,则它是集合的候选对象。(相反,如果对象仍然被引用,则它不是收集的候选对象,但您需要“准备”它。)您需要清理任何非托管资源,如数据库连接等。 通常通过实现IDisposable和调用Dispo

谢谢

编辑 感谢所有的评论和回答,似乎每个人都有相同的观点

  • 我无法理解的是,由于连接一直处于打开状态,我如何才能正确处理

  • 一旦我从传入对象复制了数据,我就不再需要该对象了,那么在DataContract对象上实现IDisposable就足够了吗
  • 我最初的问题是-

您通常不需要做任何事情


如果对象不再被引用,则它是集合的候选对象。(相反,如果对象仍然被引用,则它不是收集的候选对象,但您需要“准备”它。)

您需要清理任何非托管资源,如数据库连接等。
通常通过实现
IDisposable
和调用
Dispose

如果你有一个终结器,你应该打电话

其余的由垃圾收集器清理

编辑:
当然,您需要释放对对象的所有引用

但是,这里是这个大但是。除非您有非常特殊的情况,否则您不需要调用GC.Collect。您可能忘记发布一些资源或引用,而GC.Collect在这方面帮不了您。确保对所有一次性物品(最好是使用模式)调用
Dispose


您可能应该拿起一个内存分析器,比如,看看您的内存都到哪里去了。

如果您没有对对象的直接引用,并且内存不足,GC应该自动执行此操作。请确保在datacontext上调用.Dispose()。

只要其他人看不到该对象,该对象就已经符合收集条件;不需要更多了。这里的关键点是确保没有其他人在观看它(或者至少没有更长的生命周期):

  • 它在某个地方的田野里吗
  • 它是否在方法中的变量中是不完整的?(可能是无限循环或迭代器块)
  • 它在某处收藏吗
  • 它订阅了一些活动吗
  • 它是在一个仍然存在的闭包(lambda/anon方法)中捕获的

我真的怀疑
GC.Collect()
是否是这里的答案;如果它符合条件,它将已经被收集。如果它不可用,调用
GC.Collect()
肯定不会有帮助,而且很可能会使事情变得更糟(在无法收集有用数据时占用CPU)。

调用
GC.Collect
几乎不会阻止您摆脱内存异常,因为当.NET由于OOM而无法创建新对象时,它将调用
GC.Collect
本身。我只能想到一种情况,那就是在可终结队列中注册了未引用的对象。当这些对象引用许多其他对象时,可能会导致OOM。这个问题的解决方案实际上不是调用GC.Collect,而是确保正确地处理这些对象(并在创建这些对象时正确地实现dispose模式)。

通常使用GC.Collect

由于您试图摆脱一个非常大的集合,因此使用GC.Collect()是完全有效的。从:

。。。由于应用程序比运行时更了解其行为,因此可以通过显式强制某些集合来帮助解决问题。例如,在用户保存数据文件后,应用程序强制执行所有代的完整集合可能是有意义的

“准备”您的对象

来自优秀(来自MSDN):

如果您保留一个指向周围资源的指针,GC将无法知道您是否打算在将来使用它。这意味着您在本机代码中使用的所有显式释放对象的规则仍然适用,但大多数情况下,GC将为您处理所有事情

因此,为了确保它可以用于GC,请确保您没有对希望收集的对象的引用(例如,在集合、事件等中)。将变量设置为null将意味着在变量超出范围之前,它已准备好进行收集

此外,任何实现IDisposable的对象都应该调用其Dispose()方法来清理非托管资源

在使用GC.Collect之前

由于您的应用程序看起来像是一个服务器,因此使用服务器GC可能会解决您的问题。在多处理器场景中,它可能会运行得更频繁,性能也更高

服务器GC是为实现最大吞吐量而设计的,并且具有非常高的性能


请参阅选择要在其中使用的垃圾收集器(来自MSDN):

“我正在摆脱内存异常”-垃圾收集器设计为在这一点之前自动启动。如果不是,那么你可能会比你需要的时间更长地持有某个参考资料。我怎么知道我持有的是一个参考资料?因为一旦我合作,它就不会被收集(我承认这听起来有点像鸡/蛋)