#c_sharp #net #многопоточность
Есть много огромныйх файлов(по 4-6gb), мне нужно запустить примерно 100 потоков, чтобы каждый поток брал следующую строку из файла и обрабатывал. List_threads; int countThr; public void Run(int count) { Globals.threadAlive = 0; _threads = new List (); _threads.Clear(); countThr = count; for (int i = 0; i < count; i++) { var thread = new Thread(multiThread); thread.IsBackground = true; _threads.Add(thread); _threads[i].Start(); } } public void Abort() { Globals.threadAlive = 1; foreach (Thread thr in _threads) { thr.Abort(); } _threads.Clear(); Globals.threadAlive = 0; } private void multiThread() { for (int c = 0; c < Globals.lines.Length; c++) { //обработка строки } Globals.threadAlive = 1; Abort(); } Это будет правильное решение моей задачи?
Ответы
Ответ 1
Я предлагаю вычитывать с помощью File.ReadLines, это позволяет не загружать весь файл в память. Разбирать отдельные строки в отдельных задачах для потоков - нерентабельно, скорее всего, зависит от того, как долго занимает обработка одной строки. Поэтому предложенный вариант разбивает все строки на пакеты небольшого размера (batches) и обрабатывает их параллельно. void Main() { var filePath = Path.GetTempFileName(); File.WriteAllText(filePath, string.Join(Environment.NewLine, Enumerable.Range(0, 100001))); var batchSize = 1000; var allLines = File.ReadLines(filePath); var processedCount = 0; GetLinesInBatches(allLines, batchSize).AsParallel().ForAll(batch => { foreach (var line in batch) { Interlocked.Increment(ref processedCount); // Do something with the line. } }); Console.WriteLine("Total: {0}", processedCount); } IEnumerable> GetLinesInBatches(IEnumerable
allLines, int batchSize) { using (var e = allLines.GetEnumerator()) { bool more = false; do { var batch = new List (batchSize); for (var i = 0; i < batchSize && (more = e.MoveNext()); i++) { batch.Add(e.Current); } yield return batch; } while (more); } } Ответ 2
Если у вас доминирует чтение файла, просто читайте каждый из файлов в одном отдельном потоке. Сотня потоков не нужна и только всё испортит. Да, и потоки устарели уже давно, применяйте TPL. void ProcessFile(string path) { foreach (var line in File.ReadLines(path)) { // обработать строку } } IEnumerablepaths = ...; var processTasks = paths.Select(p => Task.Run(() => ProcessFile(p)); await Task.WhenAll(processTasks); Ленивое чтение файла позволяет не грузить гигабайты текста в память. Заодно убрали ненужную (и ошибочную) ручную работу с потоками. Если у вас обработка строки занимает ощутимое время, вам пригодится PFX: void ProcessFile(string path) { Parallel.ForEach(File.ReadLines(path), line => { // обработать строку }); }
Комментариев нет:
Отправить комментарий