处理一个StringBuilder对象

30

如何有效地处理 StringBuilder 对象?如果一个用户在单个会话中生成多个报告,则我的应用程序最终会使用大量内存。

我在几个网站上看到以下建议可能有所帮助:

StringBuilder sb = new StringBuilder(1000000);

// loop goes here adding lots of stuff to sb

exampleObject.Text = sb.ToString();

sb.Length = 0;

最后一行真的有用吗?还有其他处理这个问题的方法吗?

注意:这并不能真正阻止我的用户继续使用应用程序。我只是想知道是否有避免冗余内存使用的方法。


2
去掉1000000可能会有所帮助。 - David
3
如何做到的?预分配内存有很大帮助。让 StringBuilder 不断调整大小会使事情变得相当慢。 - Druid
3个回答

49
不,StringBuilder是一种完全托管的资源。您只需要摆脱所有对它的引用即可。其他所有事情都由垃圾回收器处理:

不需要做任何额外的处理。

StringBuilder sb = ...;
// ... do work
sb = null; // or simply let it go out of scope.

.NET中不存在确定性的delete(如同C++中,你可以释放单个对象分配的内存)。只有GC可以释放内存。通过放弃对某个对象的所有引用,你让GC能够在需要时将该对象回收。你可以通过调用System.GC.Collect方法来强制进行垃圾回收。然而,除非你确实知道自己在做什么,否则不建议操纵GC。GC是智能的,很少有必要强制进行垃圾回收。


3
如果应用程序的内存利用率过高,导致内存耗尽问题,那么添加GC.Collect()是完全有效的。.Net垃圾回收将在您尝试分配额外内存且操作系统资源不足时自动清理它,或在下一个周期中进行清理。通常情况下,除非您的应用程序非常注重性能,否则不需要使用它。 - Michael Brown

4

如果你正在生成许多报告,你可以考虑重复使用一个StringBuilder而不是为每个报告分配一个新的。


2
除非“过多的内存使用”是一个问题,否则我会让它保持原样,不用担心。
在大多数情况下,如果你有足够的内存可用,.NET通常足够智能,避免进行垃圾回收。

我遇到了一个问题,我认为在我们的一个API上随着时间的推移使用了大量未受管理的内存约4GB,该API使用了大量的StringBuilder来构建自定义查询。我使用dotMemory尝试找到问题的源头,因为在代码中看起来很正常。实际上,我发现有大量的stringbuilder、string和字典存在于未受管理的内存中,并且从未被GC回收。这些字符串是这些查询。为了更好地理解,一个查询的大小可以达到2MB,所以...它最终会慢慢增加到4GB,我们无法弄清楚为什么以及如何处理它? - Piotr Kula
如果它们没有被垃圾回收,那就意味着两种可能性之一:GC出现了问题(我从未听说这种情况发生过,但我试着保持开放的心态),或者你仍在某种程度上引用了它们。最有可能的原因是后者。你的代码是否开放在网络上供团队审查? - Lasse V. Karlsen
可能是引用问题或静态使用不当?抱歉,代码是私有的。我只是在做一些更多的分析,托管代码的GC运行良好,始终保持在200MB以下,但是非托管代码不断增长...它在IIS后面运行,所以谁知道呢?有没有办法找出非托管内存中的内容? - Piotr Kula
1
可能是,但超出了我的专业范围。 - Lasse V. Karlsen
我打算尝试进入内存转储领域,看看我是否能保持理智。 - Piotr Kula

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接