所以,我有这个代码从数据库中获取大量数据,并对该数据执行一系列计算。然而,这不是造成停顿的原因。当我拿走所有准备好的“最终”数据时,停止进入,并将其写入文本文件。
文本文件中的每一行都是根据已对其执行计算的数据创建的。每行“对应”来自数据库的记录。用户必须一次在大约30-40,000条记录上执行此文件导出通常。现在,即使我使用的是StringBuilder,由于纯粹的大量记录,这仍然会停止。
我目前在代码中做的是创建一个StringBuilder,将所有数据(在计算之后)附加到它,将其转换为String,将其添加到要从Function返回的List(Of String),然后清除StringBuilder,并对下一行执行相同的操作,并执行此操作,直到创建并附加,转换每个行,然后将其插入List。
然后,另一个类接收此List(Of String)并获取每个String并最终将其附加到文件中。
有没有人知道如何改进此代码并使其不会每次都停止服务器?之前没有找到它的原因是因为当我在本地测试时,我一次只测试1-50条记录。
提前致谢!
编辑:
r = Class.ExportFile(ID)
data = Encoding.ASCII.GetBytes(r.ResponseString)
Return File(data, "text/plain", r.DefaultFileName)
-Scott
答案 0 :(得分:3)
返回IEnumerable而不是大字符串或字符串列表,并一次写一行到该文件。这样你可以懒惰地评估数据,所以你不需要保持庞大的字符串。 e.g。
IEnumerable<string> Process() {
var rows = QueryTheDatabase();
foreach(var row in rows) {
yield return ProcessARecord(row);//process and build a string of
//one row
}
}
调用者只是在返回的IEnumerable上执行操作,并将每行写入文件。
答案 1 :(得分:2)
对我来说,你最好直接将大部分数据写入文件中 - 一定要一次写一行到StringBuilder,然后将结果字符串写入你的文件中最终出口到。这将降低内存使用率,如果您使用StreamWriter,则会缓冲写入并且性能不会受到明显影响。
答案 2 :(得分:0)
你可能会遇到内存碎片问题。在32位世界中使用 REALLY 大型动态数据结构会导致这种情况。就个人而言,我只用300mb的琴弦击中了它,但我通常会避免陷入这种情况,所以这并不是说太多。
正如其他人所说,打破它,这样你就没有这么大的字符串了。
答案 3 :(得分:0)
使用IEnumerable / iterator块而不是List。转换非常简单:将函数的返回类型从List<string>
更改为IEnumerable<string>
,然后将当前调用列表.Add()
方法的位置更改为使用yield return
的行代替。然后还要更改您的其他课程以接受IEnumerable<string>
而不是List<string>
。您可能还需要对其他方法进行类似的转换,以便以这种方式处理数据库中的整个链。
这样做是为了让你一次只在内存中保存一条记录。每条记录都将转换为字符串,并由您的输出方法即时处理。