当前位置: 首页 > 编程语言 > C#

有趣的OutOfMemoryException和StringBuilder分享

时间:2023-04-10 11:31:04 C#

有趣的OutOfMemoryException和StringBuilder我需要在循环中不断构建大字符串并保存到数据库中,目前偶尔会产生OutOfMemoryException。这基本上是基于一些数据使用XmlWriter和StringBuilder创建一个字符串。然后我从外部库调用一个方法,将该xml字符串转换为其他内容。之后,转换后的字符串将保存到数据库中。对于不同的数据,整个过程在一个循环中重复大约100次。字符串本身并不太大(每个小于500kBy),并且在此循环期间进程内存不会增加。但是,偶尔我会在StringBuilder.Append处收到OutOfMemeoryExcpetion。有趣的是,这个异常不会导致崩溃。我可以捕获该异常并继续循环。这里发生了什么?为什么我会得到一个OutOfMemoryException尽管系统中仍然有足够的空闲内存?这是一些GC堆问题吗?鉴于我无法绕过转换所有这些字符串,我该怎么做才能使这项工作可靠地进行?我应该强制GC收集吗?Thread.Sleep应该放在一个循环中吗?我应该停止使用StringBuilder吗?它是否应该在遇到OutOfMemoryException时重试?有内存但没有连续的段来处理字符串生成器的大小。您必须知道,每当字符串生成器的缓冲区变得太短时,它的大小就会加倍。如果您可以(在构造函数中)定义构建器的大小,那就更好了。当您处理完大量对象后,您可以调用GC.Collect()。实际上,当你有一个OutOfMemory时,它通常显示一个糟糕的设计,你可能正在使用硬盘驱动器(临时文件)而不是内存,你不应该一次又一次地分配内存(尝试重用对象/缓冲区/。..).我强烈建议你阅读这篇文章“OutofMemory”并不是指EricLippert的物理内存。在进行数据生成时尽量重用StringBuilder对象。在使用之后或之前,只需将StringBuilder的大小重置为0并开始追加。这将减少分配的数量,并可能使OutOfMemory情况非常罕见。为了说明我的观点:voidMainProgram(){StringBuilderbuilder=newStringBuilder(2*1024);//2KbPerformOperation(建造者);执行操作(建造者);执行操作(建造者);执行操作(建造者);}voidPerformOperation(StringBuilderbuilder){builder.Length=0;////在这里完成工作builder.Append(...);//}根据您提到的大小,您可能会遇到大对象堆(LOH)碎片。重用StringBuilder对象不是直接的解决方案,您需要掌握底层缓冲区。如果可能,请事先计算或估计大小并进行预分配。如果您整理您的分配可能会有所帮助,比方说20k左右的倍数。这提高了重用性。以上就是C#学习教程的全部内容:有趣的OutOfMemoryException和StringBuilder。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右边联系管理员删除。如需转载请注明出处: