System.OutofMemoryException
我怎么可以解决这个问题? 我应该写入内存的比较,然后还有其他内容将结果写入磁盘/rdbms。即创建一个缓冲区。
实际上,这确实取决于您的环境,尤其是您的操作系统X86或X64。在此处查看更多详细信息:
记录深度
1。您有高级方案,您需要流式传输。精确的解决方案取决于您从何处提取数据。如果从SQL数据库中获取数据,则可以将流媒体用于SQLDATAREADER,在这种情况下,它与异步紧密结合,示例代码:
using (SqlDataReader reader = await command.ExecuteReaderAsync(CommandBehavior.SequentialAccess))
{
if (await reader.ReadAsync())
{
if (!(await reader.IsDBNullAsync(0)))
{
using (var dataStream = reader.GetStream(0))
{
//process the data
}
}
}
}
。但是,请记住,这种方法迫使您在连接字符串中使用异步以及处理异步代码,这始终是额外的复杂性,尤其是当您希望用Specs/test覆盖它时。 2.yet另一种方法是批处理,即将数据缓冲至一定可接受的限制,然后将批次暴露于消费代码之后,此后继续获取新的数据,除非所有内容已加载,否则示例代码:
while(true)
{
int count = 0;
bool canRead = reader.Read();
while(canRead)
{
canRead = reader.Read();
count++;
if (count >= batchSize)
break;
}
if (!canRead)
break;
}
您可以通过估计1行数据的大小(基于表模式,
MMSDNArticles),或者只是使其可配置并以最合适的值进行播放来大致计算批量的大小。这种方法的主要优点是,您需要最小的代码更改,并且代码本身仍然同步。缺点是,您必须每次保持主动连接或打开新连接,而要维护您已经阅读的记录以及仍然需要获取的记录。
最终,两种选择都会迫使您注意一些更高级的问题,例如,如果仅获取数据的一部分,然后丢失了连接(需要一些故障机制),可以取消特定超时的长期检索操作等。 得出结论,如果您不想处理大数据引入的其他复杂性,请将此任务委派给市场上的任何内容,即数据库或第三方框架。如果您觉得自己的团队有足够的技能,那就继续自己实施 - 保持磁盘文件中的比较结果,使用内存中缓存或将数据推入数据库
首先取决于您正在使用的处理器体系结构。如果您使用的是32位体系结构,则每个进程只有2GB的内存。在这种情况下,您真的受到可以存储在那里的东西的限制。 64位处理器允许更多的内存,在这种情况下应该很好。
另一件事要注意的是,在内存中例外并不意味着根本没有足够的内存,这意味着该过程无法分配所需内存的连续块。如果您试图分配一个非常大的对象,例如大小为1GB的数组,则需要找到该1GB的连续内存块。 Concrete答案取决于您的情况,但是总的来说,我将首先尝试切换到64位体系结构,然后检查分配的最大对象有多大。如果没有任何改进,您应该开始考虑将一些信息存储到磁盘上。