【问题标题】:System.OutOfMemoryException: Exception of Type 'System.OutOfMemory' was thrownSystem.OutOfMemoryException:引发了“System.OutOfMemory”类型的异常
【发布时间】:2015-05-05 11:44:38
【问题描述】:
private List<T> ReadCurrentFile(string currentExtractedFile, PurgingDetails purgingParams)
{
    List<T> thinLogDoList = new List<T>();
    using (StreamReader sr = new StreamReader(currentExtractedFile))
    {
        string currentLine = string.Empty;
        Dictionary<string, string> ColumnNamesDictionary = null;
        while ((currentLine = sr.ReadLine()) != null)
        {
            if (currentLine.IsNotNullOrEmpty() && currentLine.Contains("Æ"))
            {
                string[] columnNames = currentLine.Split(new char[] { 'Æ' });
                ColumnNamesDictionary = FillColumnNameDictionary(columnNames);

                if (CheckForValidConditions(ColumnNamesDictionary, purgingParams))
                {
                    thinLogDoList.Add(FillThinLogDO(ColumnNamesDictionary));
                }
            }
        }
    }
    return thinLogDoList;
}

(以上代码用于读取文件并通过填充对象将数据添加到列表中。) 该函数正在读取 zip 文件中大小为 10 MB 的文件,首先我提取 zip 文件,然后读取数据,使用此函数并将其存储到 List 中,然后删除提取的 zip 文件。它适用于大约 6L(6,00,000) 数据,但在该数据之上它会引发异常。 我想阅读更多数据 10L(10,00,000) 我该怎么做?

【问题讨论】:

  • 如果你使用印度格式的数字会很混乱
  • 正确,你真的无法做到这一点。一种方法是直接产生/返回 IEnumerable 或者甚至可能使用字典。使用字典时,我的性能得到了很大的改进,问题也更少了。
  • 文件格式应该是什么?
  • 文件格式是“.dat”&我已经在我的代码中使用了字典

标签: c#-4.0


【解决方案1】:

不返回列表。相反,使用 yield return 来遍历数据:

private IEnumerable<i1LogThinDO> ReadCurrentFile(string currentExtractedFile,
                                                 PurgingDetails purgingParams)
{
    using (StreamReader sr = new StreamReader(currentExtractedFile))
    {
        string currentLine = string.Empty;
        Dictionary<string, string> ColumnNamesDictionary = null;
        while ((currentLine = sr.ReadLine()) != null)
        {
            if (currentLine.IsNotNullOrEmpty() && currentLine.Contains("Æ"))
            {
                string[] columnNames = currentLine.Split(new char[] { 'Æ' });
                ColumnNamesDictionary = FillColumnNameDictionary(columnNames);

                if (CheckForValidConditions(ColumnNamesDictionary, purgingParams))
                {
                    yield return FillThinLogDO(ColumnNamesDictionary);
                }
            }
        }
    }
}

这样,球就在呼叫者的院子里。调用者必须能够处理从此方法返回的数据,而不会将它们全部保存在内存中。这可能意味着您还必须重新设计调用方法,但如果您可以在不将数据保存在内存中的情况下完成所有处理,则会大大减少应用程序的内存占用。

【讨论】:

  • 感谢@Zoran,但您的解决方案也不起作用。
  • 您是否在此方法上调用 ToList() 或类似的东西?如果此方法的任何调用者具体化列表,则此解决方案将不起作用。您必须修复调用者以在 foreach 循环中运行,并且永远不要调用 ToList() 或类似的东西。
  • 仍然抛出异常,我该如何处理?
  • 异常是在这个函数中抛出的,还是在调用者身上抛出的?如果抛出 OutOfMemory 异常,那么应用程序中肯定有人将这个对象流转换为列表,而这正是不应该做的事情。
猜你喜欢
  • 1970-01-01
  • 2013-01-14
  • 2013-08-28
  • 2015-07-18
  • 2011-02-14
相关资源
最近更新 更多