是否应定期调用GC.Collect()?

Mon*_*gix 5 .net c# io garbage-collection readfile

我最近发布了一篇关于日志文件阅读器由于内存不足错误而失败的文章> 内存错误归档日志文件

在我有机会尝试更简单的方法(调用日志文件的名称,其中有一个日期以防止归档)这显然意味着重写方法等,我首先尝试了垃圾收集选项,因为我从来没有使用它,例如GC.Collect的().

如果在尝试读取日志文件内容时抛出内存错误,则将其置于第一个try/catch中,并且它似乎释放了一半的内存,例如从此过程中使用的调试文件中释放(因为日志文件明显不在动作所以这是为了帮助我调试事后)我从昨晚的归档过程得到这个回应.

Attempt Archive
Take contents of current file with ReadFileString  (this is my custom stream reader method I wrote which you can see in the original article)
Taken contents of current file!
In TRY/CATCH - Out of Memory Exception - Try GC.Collect()
Memory used before collection: **498671500**
Memory used after collection: **250841460**
Try again with ReadFileString
How much content have we got? Content Length is **123595955**
We have content from the old log file
Run Code Online (Sandbox Code Playgroud)

所以GC.Collect似乎解决了读取文件问题.

但是我只是想知道它从这个调试中解放出来的内存类型,因为当我调用GC.Collect()时它会删除247.83MB的内存.

因此,我想知道它正在释放什么样的对象或内存,因为我认为.NET应该具有良好的内置垃圾收集,如果它随着时间的推移使这个"可用"的内存变得非常"我可以定期调用GC.Collect ()经常释放内存或产生的内存量只是因为它在第一次尝试将日志文件读入内存时失败了?

显然它已经有一段时间没有使用大文件了,直到我尝试了之前从未使用过的GC.Collect所以我只是想知道内存来自何处,何时被正常收集,应该被调用别处.

这是一个Windows服务应用程序,它使用多个计时器来控制运行所需的每个作业,从而使用JSON对第三方API进行许多HTTP调用.因此,除非我手动停止服务,否则它会持续运行.

所以我应该每天晚上调用GC.Collect()一次,就像其他人们所说的将垃圾收集留给系统一样好的做法,但是从这个实例中它有助于快速解决内存不足错误的问题.抛出(我有一台运行14GB的64位计算机).

Ian*_*ose 6

首先要仔细检查是否正在关闭(处理)所有文件对象,否则在GC发现您忘记关闭文件之前,内部文件缓冲区将不会被释放.

如果您不需要复制文件,只需将其重命名(FileInfo.Rename).这是处理日志文件的常用方法.

如果您不需要处理数据,请使用FileInfo.CopyToCopyTo(Stream)方法,这就是使用合理的小缓冲区复制文本的原因,永远不需要分配内存来保存所有文本.同时.

如果确实需要处理文本,一次读取一行,这将导致创建大量小字符串,而不是一个非常大的字符串. .net GC非常擅长回收小型短寿命物体. 如果您将整个日志文件同时存储在内存中,那就没有意义了.创建一个返回文件中行的自定义迭代器将是一种方法.


meh*_*afa -7

垃圾收集器通常会自动收集不再使用和引用的托管对象。通常不需要(或不应该)GC.Collect()手动调用方法。但例如(在本例中)当您打电话时:

 queue.Dequeue(item)... 
Run Code Online (Sandbox Code Playgroud)

在长循环中,没有指针或变量指向已删除的对象,但由于它仍在方法范围内,垃圾收集器不会收集它,直到内存变得非常低。如果您遇到这样的紧急情况,您可以手动调用它。

  • 范围界定没有相关性。只要将来不再读取本地数据,无论范围如何,它都有资格被收集。您必须编写非常复杂的代码才能防止其正常工作。作用域仅对编译器和调试器重要 - 在调试器中运行时,.NET 将遵循本地作用域以帮助调试。毕竟,如果“GC.Collect”可以收集这些对象,那么它们一定已经无法访问。 (6认同)