Параллельная проблема памяти Foreach - PullRequest
6 голосов
/ 11 мая 2011

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

 FileInfo[] fileInfoCollection = directory.GetFiles();
 Parallel.ForEach(fileInfoCollection, ProcessWorkerItem);

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

В «ProcessWorkerItem» я запускаю алгоритм, основанный на строковых данных файла.Кроме того, я использую log4net для ведения журналов, и в этом методе есть много связей с сервером SQL.

Вот некоторая информация, Размер файлов: 1-2 КБ XML-файлы.Я читаю эти файлы, и процесс зависит от содержимого файла.Он идентифицирует некоторые ключевые слова в строке и генерирует другой формат XML.Ключевые слова находятся в базе данных сервера SQL (почти 2000 слов).

Ответы [ 3 ]

7 голосов
/ 11 мая 2011

Ну, а что делает ProcessWorkerItem? Вы можете изменить это, чтобы использовать меньше памяти (например, передавать данные, а не загружать их все сразу), или вы можете явно ограничить степень параллелизма, используя this overload и ParallelOptions.MaxDegreeOfParallelism. По сути, вы хотите избегать попыток обработать все 3000 файлов одновременно :) IIRC, Parallel Extensions «заметят», если ваши задачи кажутся ограниченными с помощью ввода-вывода, и позволят выполнить больше, чем обычно, числа одновременно, что не совсем то, что нужно Вы хотите здесь, так как ваша память также связана.

2 голосов
/ 11 мая 2011

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

Возможно, стоит попробовать Rx расширения и использовать его метод Throttle для управления / составления вашей обработки?

0 голосов
/ 12 мая 2011

Я нашел ошибку, которая вызвала утечку памяти, я использовал шаблон Unit Of Work с каркасом сущностейВ единице работы я сохраняю контекст в хеш-таблице с именем потока в качестве хеш-ключа.Когда я использую многопоточность, хэш-таблица продолжает расти, и это вызывает утечку памяти.Поэтому я добавил дополнительный метод в единицу работы, чтобы удалить элемент из хеш-таблицы после выполнения задачи потока.

public static void DisposeUnitOfWork()
        {
            IUnitOfWork unitOfWork = GetUnitOfWork();

            if (unitOfWork != null)
            {
                unitOfWork.Dispose();
                hashTable.Remove(Thread.CurrentThread.Name);


            }
        }
...