如何释放或回收C#中的字符串?

如何释放或回收C#中的字符串?,c#,string,garbage-collection,immutability,C#,String,Garbage Collection,Immutability,我有一个大字符串(例如20MB) 我现在正在分析这个字符串。问题是C#中的字符串是不可变的;这意味着,一旦我创建了一个子字符串并查看它,内存就被浪费了 由于所有的处理,内存被不再使用、需要或引用的字符串对象阻塞;但垃圾收集器释放它们的时间太长了 因此,应用程序内存不足 我可以使用表现不佳的俱乐部方法,并打几千个电话给: GC.Collect(); 到处都是,但这并不能真正解决问题 我知道创建大字符串时存在StringBuilder 我知道TextReader可以将字符串读入字符数组 我需要以某

我有一个大字符串(例如20MB)

我现在正在分析这个字符串。问题是C#中的字符串是不可变的;这意味着,一旦我创建了一个子字符串并查看它,内存就被浪费了

由于所有的处理,内存被不再使用、需要或引用的
字符串
对象阻塞;但垃圾收集器释放它们的时间太长了

因此,应用程序内存不足

我可以使用表现不佳的俱乐部方法,并打几千个电话给:

GC.Collect();
到处都是,但这并不能真正解决问题

我知道创建大字符串时存在
StringBuilder

我知道
TextReader
可以将
字符串
读入
字符
数组


我需要以某种方式“重用”字符串,使其不再是不可变的,这样我就不会在1k可用时不必要地分配千兆字节的内存。

您是否有一些示例代码来测试可能的解决方案是否能很好地工作

但一般来说,任何大于85KB的对象都将被分配到上,这可能会减少垃圾收集的频率


此外,如果您真的在努力推动CPU,垃圾收集器可能会减少执行其工作的频率,试图避开您的影响。

如果您的应用程序正在消亡,这可能是因为您仍然有对字符串的引用,而不是因为垃圾收集器没有清理它们。我见过它像那样失败,但这不太可能。您是否使用了探查器来检查内存中是否一次有很多字符串


它的长短不一之处在于,您不能重用字符串来存储不同的数据——这就是无法做到的。如果你愿意的话,你可以写你自己的等价物——但是有效和正确地写的机会非常渺茫。现在,如果您能提供更多关于您正在做的事情的信息,我们可能会建议不使用太多内存的替代方法。

考虑到这一事实,我建议您不能在C#中重用字符串,请使用。您只需将字符串保存在磁盘上,并通过映射文件(如流)以性能/内存消耗卓越关系对其进行处理。在本例中,您重用了相同的文件、相同的流,并且只对在该精确时刻需要的数据的一小部分(如字符串)进行操作,然后立即将其丢弃


这个解决方案严格地取决于你的项目需求,但是我认为你可以认真考虑的解决方案之一,特别是内存消耗会急剧下降,但是你会在性能方面“付出”一些东西。

< P>这个问题已经将近10年了。现在,请查看-使用
AsSpan()
方法从字符串中实例化一个。然后,您可以应用索引运算符将切片作为跨度获取,而无需分配任何新字符串。

您不能这样做,除非您将其锁定并变得不安全(您可以使用不安全代码直接修改缓冲区)。我认为您可能需要使用一个流,一次只读取一点点位,这取决于您对数据所做的操作,实现您自己的“string”类可能是有意义的,其中子字符串实际上是对父字符串的引用(类似于Java对
子字符串
)。这样,只有原始字符串数据存储在内存中。你可能也想看看这篇文章:我猜你仍然有一些你不知道的参考资料。如果你正在制作一个一千万字符的字符串,很可能你做错了什么。为什么你的记忆中有这么大的一根弦?你需要把整个东西都放在内存中才能解析它吗?解析器通常以仅向前的方式使用字符串,并具有有限的前瞻性;为什么您需要立即将整个字符串存储在内存中?很可能Jon是正确的,并且您持有对字符串的某种引用,因此阻止了清理。但是,如果不是这样的话,你必须重复使用你的字符串的内存,你可以考虑使用“不安全”的代码,但只是作为最后的手段。你可以在这里找到更多的细节。我们本身没有参考资料;如果我们强制垃圾收集器运行,内存将被释放。在某种程度上,你可以存在主义地说我们持有内存,因为它是在我的进程空间中分配的。没有什么能阻止GC释放它——除了它运行速度不够快。@Ian:这至少是不寻常的。子字符串有多大?原始大字符串的来源是什么,您能流式传输它吗(例如,一次处理一行)?它们是
MHT
文件;单文件编码网页;客户将其用作有关人员(例如FBI头号通缉犯)信息的序列化格式。它包含base-64编码的图像,足够大,适合面部识别。需要时,我们会处理几十万个。有时
mht
文件将位于硬盘或CD上;但它们也可以从我们的
WebRequest
中获取。每一个都被加载到内存中(作为字符串)并进行处理。@Ian:你能流式处理它们,而不是一次将整个页面加载到内存中吗?即使文件是内存映射的,我们仍然存在将部分读入字符串的问题—有时是大部分,有时是小部分,有时,较小的部分来自较大的部分。最终,所有这些未收集的字符串都会阻塞可用内存,或者导致交换死亡。@Ian频繁但短期使用相对较小的字符串,因为在这种情况下,您不需要在内存中加载所有数据,我认为应该会产生显著的不同。