Интенсивный файловый ввод / вывод и обработка данных в C # - PullRequest
4 голосов
/ 21 января 2010

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

Прямо сейчас эта часть приложения является однопоточной (чтение записи, обработка ее, чтение следующей записи и т. Д.). Я думаю, что было бы более эффективно читать записи в очереди в одном потоке и обрабатывать их в другом потоке небольшими блоками или по мере их поступления.

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

Ответы [ 3 ]

3 голосов
/ 21 января 2010

Вы можете получить выгоду, если сможете сбалансировать время обработки записей с временем чтением записей; в этом случае вы можете использовать настройку производителя / потребителя, например синхронизированная очередь и рабочий (или несколько) перевод в очередь и обработка. Я также мог бы испытать желание исследовать параллельные расширения; очень легко написать IEnumerable<T> версию вашего кода чтения, после чего Parallel.ForEach (или один из других Parallel методов) должен фактически делать все, что вы хотите; например:

static IEnumerable<Person> ReadPeople(string path) {
    using(var reader = File.OpenText(path)) {
        string line;
        while((line = reader.ReadLine()) != null) {
            string[] parts = line.Split(',');
            yield return new Person(parts[0], int.Parse(parts[1]);
        }
    }
}
1 голос
/ 21 января 2010

Вы также можете посмотреть на асинхронный ввод / вывод . В этом стиле вы начнете файловую операцию из основного потока, затем она продолжит работу в фоновом режиме, а после завершения вызовет указанный вами обратный вызов. В то же время вы можете продолжать делать другие вещи (например, обработку данных). Например, вы можете запустить асинхронную операцию, чтобы прочитать следующие 1000 байтов, затем обработать уже имеющиеся 1000 байтов и дождаться следующего килобайта.

К сожалению, программирование асинхронных операций в C # немного болезненно. Существует образец MSDN , но он совсем не хорош. Это может быть легко решено в F # с использованием асинхронных рабочих процессов. Я написал статью, которая объясняет проблему и показывает, как сделать подобное с помощью C # итераторов .

Более многообещающим решением для C # является библиотека Wintellect PowerThreading, которая поддерживает аналогичный прием с использованием итераторов C #. В MSDN Concurrency Affairs есть хорошая вводная статья Джеффри Рихтера.

1 голос
/ 21 января 2010

Взгляните на этот учебник, он содержит все, что вам нужно ... Это учебники Microsoft, включая примеры кода для подобного случая, как вы описываете. Ваш производитель заполняет очередь, а потребитель выталкивает записи.

Создание, запуск и взаимодействие между потоками

Синхронизация двух потоков: производителя и потребителя

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...