【发布时间】:2012-02-02 18:27:12
【问题描述】:
小问题
我有一个运行 180,000 次的循环。在每次迭代结束时,它应该将结果附加到一个实时更新的文本框。
使用MyTextBox.Text += someValue 会导致应用程序占用大量内存,并在几千条记录后耗尽可用内存。
有没有更有效的方法将文本附加到TextBox.Text 180,000 次?
编辑我真的不关心这个特定案例的结果,但是我想知道为什么这似乎是一个内存猪,以及是否有更有效的方法来附加文本到一个文本框。
长(原始)问题
我有一个小应用程序,它读取 CSV 文件中的 ID 号列表并为每个 ID 生成一份 PDF 报告。生成每个 pdf 文件后,ResultsTextBox.Text 会附加已处理且已成功处理的报告的 ID 号。 进程在后台线程上运行,因此 ResultsTextBox 会随着项目的处理而实时更新
我目前正在针对 180,000 个 ID 号运行该应用程序,但是该应用程序占用的内存随着时间的推移呈指数增长。它从大约 90K 开始,但到大约 3000 条记录时,它占用了大约 250MB,到 4000 条记录时,应用程序占用了大约 500MB 的内存。
如果我注释掉结果文本框的更新,内存在大约 90K 时保持相对稳定,所以我可以假设写入 ResultsText.Text += someValue 是导致它吃掉内存的原因。
我的问题是,这是为什么呢?将数据附加到不占用内存的 TextBox.Text 的更好方法是什么?
我的代码如下所示:
try
{
report.SetParameterValue("Id", id);
report.ExportToDisk(ExportFormatType.PortableDocFormat,
string.Format(@"{0}\{1}.pdf", new object[] { outputLocation, id}));
// ResultsText.Text += string.Format("Exported {0}\r\n", id);
}
catch (Exception ex)
{
ErrorsText.Text += string.Format("Failed to export {0}: {1}\r\n",
new object[] { id, ex.Message });
}
还值得一提的是,该应用程序是一次性的,生成所有报告需要几个小时(或几天:))并不重要。我主要担心的是,如果它达到系统内存限制,它将停止运行。
我可以保留更新结果文本框注释掉的行来运行这个东西,但我想知道是否有一种更节省内存的方式将数据附加到 TextBox.Text 以供将来的项目使用。
【问题讨论】:
-
您可以尝试使用
StringBuilder附加文本,然后在完成后将StringBuilder值分配给文本框。 -
我不知道它是否会改变任何东西,但如果你有一个附加新 Id-s 的 StringBuilder 并且你将使用一个属性,该属性会使用字符串生成器的新值进行更新并将其绑定到您的 textbox.text 属性。
-
为什么在调用string.Format时要初始化一个对象数组?有些重载需要 2 个参数,因此您可以避免创建数组。另外,当您使用参数重载时,会在幕后为您创建数组。
-
字符串连接不一定是低效的。如果您要跨多个工作单元连接字符串并在每个工作单元之间显示结果,它将比 StringBuilder 更有效。当您通过循环构建字符串然后只在循环结束时写出结果时,StringBuilder 确实更有效。
-
我想说的是,这台机器令人印象深刻:-)