2014-09-19 117 views
2

我正在通过不同的方式来读取CSV文件并发现一个“奇怪”的问题。问题是,当我使用一个控制台应用这种方法:为什么ReadAllLines在WPF中工作但在ConsoleApp中不工作

 var lines = File.ReadAllLines(fileName); // OutOfMemoryException 
     foreach (var line in lines) 
     { 
      //doing stuff 
     } 

我得到一个OutOfMemoryException,但是当我用同样的方法在我的WPF项目,它工作正常。 我测试这个文件是730MB,我知道不要在更大的CSV文件上使用ReadAllLines,但为什么这种方法在WPF应用程序中工作,但不是在控制台应用程序中?

+1

你怎么知道它的工作原理?你真的到达WPF应用程序中的foreach循环吗? – Dirk 2014-09-19 09:16:25

+1

真的,对于一个文件,你会更好地流,而不是一气呵成地处理它 – Sayse 2014-09-19 09:19:06

+0

我到了foreach循环,我甚至可以显示数据网格中的所有行,正如我所说我知道不使用ReadAllLines在一个大小的文件上。 – Simon 2014-09-19 09:29:53

回答

5

您正在使用32位进程并遭受地址空间碎片化。这意味着运行时不能分配足够的连续内存,尽管总共有足够的内存空闲。 WPF可能只是倾向于拥有更好的内存布局。

将项目更改为64位。

或者,使用File.ReadLines流式传输文件。

+0

或File.ReadLines()。有一个相关的帖子,http://stackoverflow.com/questions/9475355/64bit-console-app-threadpool-out-of-memory。 – 2014-09-19 09:21:53

3

我怀疑你的WPF应用程序是在任何CPU上编译的,而你在x32目标CPU上控制应用程序。如果您在x64机器上运行应用程序,则与x32编译控制台应用程序相比,WPF应用程序可以使用更多的内存,该应用程序大约限制在1.5 GB。

此外,我建议改变你的方法,如果可能的话,不要一次处理整个文件。

0

我不会直接回答你的问题,但我认为需要指出的是OutOfMemoryException经常表明你的程序存在太多的内存压力,或者没有使用可用的资源在一个非常好的方式。

就你而言,通过调用File.ReadAllLines有效缓存整个文件。但是,这可能根本就没有必要,因为之后你会逐行处理它。也就是说,它可能足以只在内存中一行文本在任何一个时刻:

  • 由于this answer说,你可以使用File.ReadLines到流文件中的行由行。

  • 如果您的目标.NET Framework版本早于.NET 4,则该方法将不可用。你可以用自己的实现来替代它,例如:

    // using System.IO; 
    static IEnumerable<string> ReadLines(string filePath) 
    { 
        using (var input = File.OpenText(filePath)) 
        { 
         while (!input.EndOfStream) 
         { 
          string line = input.ReadLine(); 
          yield return line; 
         } 
        } 
    } 
    
+1

文件。ReadLines()更加优雅;然后OP意识到这不是最佳实践,但要求技术人员解释控制台和WPF应用程序之间意外的差异,而不是如何避免Console prob。 – 2014-09-19 09:34:07

+0

@PeterSchneider:关于'File.ReadLines'你绝对正确。我已经更新了我的答案。关于OP的问题,就像我提到的,我甚至没有试图回答这个问题。但我认为还是值得指出的是,通过使可用资源变得更智能(在这里:更保守),可以完全防止这个问题。 – stakx 2014-09-19 09:42:23

+0

一切都是真的 - 这意味着它不是一个答案,这是一个评论。 – 2014-09-19 09:48:09

相关问题