Почему ReadAllLines работает в WPF, а не в ConsoleApp

Я делаю несколько тестов на различные способы чтения файла CSV и обнаружил "странную" проблему. Проблема в том, что когда я использую этот метод в консольном приложении:

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

Я получаю OutOfMemoryException, но когда я использую тот же метод в моем проекте WPF, он работает нормально. Файл, на котором я тестирую этот файл, составляет 730 МБ, и я знаю, что не следует использовать ReadAllLines для больших файлов CSV, но почему этот метод работает в приложении WPF, а не в консольном приложении?

3 ответа

Решение

Вы используете 32-битный процесс и страдаете от фрагментации адресного пространства. Это означает, что среда выполнения не может выделить достаточно непрерывной памяти, хотя в целом достаточно памяти будет свободно. WPF может иметь тенденцию иметь лучшую разметку памяти.

Измените проект на 64-битный.

Или потоковое файл с помощью File.ReadLines,

Я подозреваю, что ваше приложение WPF скомпилировано на любом процессоре, а ваше консольное приложение на целевом процессоре x32. Если вы запускаете приложения на компьютере с архитектурой x64, приложение WPF может использовать гораздо больше памяти по сравнению с консольным приложением с архитектурой x32, которое ограничено примерно 1,5 ГБ.

Кроме того, я предлагаю изменить ваш подход и, если возможно, не обрабатывать весь файл сразу.

Я не буду давать вам прямой ответ на ваш вопрос, но я думаю, что важно отметить, что OutOfMemoryException часто указывает на то, что ваша программа слишком сильно нагружает память или не очень хорошо использует доступные ресурсы.

В вашем случае вы эффективно кэшируете весь файл в памяти, вызывая File.ReadAllLines, Однако это может быть вовсе не нужно, потому что сразу после этого вы будете обрабатывать его построчно. То есть может быть достаточно иметь в памяти только одну строку текста:

  • Как говорится в этом ответе, вы можете использовать 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;
            }
        }
    }
    
Другие вопросы по тегам