C# 强制垃圾收集以确保GC获胜是一个好主意吗';以后不要检查很大的物体?

C# 强制垃圾收集以确保GC获胜是一个好主意吗';以后不要检查很大的物体?,c#,garbage-collection,C#,Garbage Collection,我创建了一个服务器应用程序,它必须在开始监听客户端之前处理一些数据(这是一个相当繁重的过程)。结果,它分配了只使用一次的内存(大约30MB) 强制垃圾收集对我有好处吗?还是让GC完成它的工作 此外,我还必须使用.NET 3.5,据我所知,垃圾收集将中断线程,这就是为什么我要强制垃圾收集器。好的,看,垃圾收集仍然只是一种启发式方法,它试图尽可能地进行猜测,但也有可能,你有一个合理的要求,在特定的时间里,你知道的比它更好 以一个拥有大量资产的游戏为例。当您切换到一个新区域时,会弹出一个加载屏幕,开始

我创建了一个服务器应用程序,它必须在开始监听客户端之前处理一些数据(这是一个相当繁重的过程)。结果,它分配了只使用一次的内存(大约30MB)

强制垃圾收集对我有好处吗?还是让GC完成它的工作


此外,我还必须使用.NET 3.5,据我所知,垃圾收集将中断线程,这就是为什么我要强制垃圾收集器。

好的,看,垃圾收集仍然只是一种启发式方法,它试图尽可能地进行猜测,但也有可能,你有一个合理的要求,在特定的时间里,你知道的比它更好

以一个拥有大量资产的游戏为例。当您切换到一个新区域时,会弹出一个加载屏幕,开始加载新数据,释放对旧数据的引用。它还不会被收集,因为你还没有达到你的阈值,但是当你开始在每一帧创建你的小矩阵来展示你的游戏时,你可能会很快达到它,然后当你卸载数百兆的数据并移动其他所有东西来压缩队列时,你会有一个(可能是明显的)口吃

现在,你可以在新资产加载后强制收集,因为用户已经处于“空闲”模式,盯着你的进度条,他不会注意到小口吃,你的游戏在加载后会变得更流畅


真正的诀窍是知道什么时候该干涉,什么时候不该干涉。当有疑问时,不要这样做——不管发生什么,收集都会发生,而让它发生得更频繁只会让你的应用程序看起来更混乱。你需要一些东西来“隐藏”它,比如一个长任务,它用一个进度条锁定你的应用程序,以某种方式生成许多最终的对象——实际上,游戏加载屏幕是我唯一能想到的,但是YMMV。

托管语言的一部分要点是,你(大概)不必担心垃圾收集,曾经只有在非常特定的情况下,手动调用垃圾收集器才有用,而这几乎肯定不是其中之一

您可以阅读GC背后的一些语义,以及是什么使它变快而不是变慢,这可能是一个很好的理论阅读,这样您就知道发生了什么

同时,对于您的具体问题,我认为您应该看看接口。如果您有一个特定的大对象,并且您很关心它,那么在它上实现IDisposable接口将允许您使用语句将工作包装在一个
中,这将保证在处理完该对象后立即将其处理掉。另一方面,它保证了这个大对象将有一个活动的、打开的句柄,因此在using语句结束之前,GC不可能拾取它


这可能比试图手动使用GC更好地解决您的问题,GC在设计上对最终程序员来说是一个黑盒子。

您没有说明如何分配30MB内存,但它非常重要。如果您正在分配非托管内存,则GC不知道这一点(尽管您可以用方法告诉它)。在这种情况下,您应该在处理非托管内存的类上实现IDisposable,并在处理完对象后显式调用Dispose

如果要分配托管内存,只需让GC执行其工作,除非:

  • 你只是碰巧知道,在你完成了这个物体之后,你的活动和记忆总是会暂时停止
  • 实际上,您已经观察到有证据表明GC在稍后的时间点导致了性能问题

据我所知,您很少需要自己使用.NET调用GC。我只知道当你使用很多互操作的东西时。为什么不直接处理你的对象或者使用using结构,让框架自己处理它呢?我同意第一个答案,GC不喜欢强制。我也同意,通常最好让它自己照顾自己。垃圾收集也在后台线程中运行,因此不应中断您的工作application@paul不会,因为我使用的是.NET3.5。如果没有更多的对象引用,GC将为您清理它。老实说,我认为你的代码有漏洞。如果你能发布你的代码,我们就可以发现问题。处理对象会很好,但我无法访问此代码的某些部分。我认为,除非有必要,否则最好不要强制使用GC。如果您在代码中使用它,您至少应该能够实现一个
IDisposable
包装器对象。这样做肯定有点笨拙,但在理论上的理想世界中,如果没有任何笨拙,您将可以访问所有需要使用的代码!“当有疑问时,不要”仅仅是对它的完美总结。@dgvid,注意有时候做它是值得的。@Blindy,但只有在你没有疑问的情况下。