读multithreading的大txt文件?

我有100000行的大型txt文件。 我需要启动n-count个线程并从该文件中为每个线程提供uniq行。 做这个的最好方式是什么? 我想我需要逐行读取文件,迭代器必须是全局的才能锁定它。 将txt文件加载到列表将非常耗时,我可以收到OutofMemoryexception。 有任何想法吗? 用一些代码帮助plz。

您可以使用File.ReadLines方法逐行读取文件而不立即将整个文件加载到内存中,并使用Parallel.ForEach方法并行处理多个线程中的行:

 Parallel.ForEach(File.ReadLines("file.txt"), (line, _, lineNumber) => { // your code here }); 

在执行我自己的基准测试以将61,277,203行加载到内存中并将值推送到Dictionary / ConcurrentDictionary()之后,结果似乎支持@dtb上面的答案,使用以下方法是最快的:

 Parallel.ForEach(File.ReadLines(catalogPath), line => { }); 

我的测试还显示了以下内容:

  1. File.ReadAllLines()和File.ReadAllLines()。AsParallel()似乎在这个大小的文件上以几乎完全相同的速度运行。 看看我的CPU活动,看起来它们似乎都使用了我的8个内核中的两个?
  2. 首先使用File.ReadAllLines()读取所有数据似乎比在Parallel.ForEach()循环中使用File.ReadLines()要慢得多。
  3. 我还尝试了一个生产者/消费者或MapReduce样式模式,其中一个线程用于读取数据,另一个线程用于处理它。 这似乎也没有超越上面的简单模式。

我已经包含了此模式的示例以供参考,因为它未包含在此页面中:

 var inputLines = new BlockingCollection(); ConcurrentDictionary catalog = new ConcurrentDictionary(); var readLines = Task.Factory.StartNew(() => { foreach (var line in File.ReadLines(catalogPath)) inputLines.Add(line); inputLines.CompleteAdding(); }); var processLines = Task.Factory.StartNew(() => { Parallel.ForEach(inputLines.GetConsumingEnumerable(), line => { string[] lineFields = line.Split('\t'); int genomicId = int.Parse(lineFields[3]); int taxId = int.Parse(lineFields[0]); catalog.TryAdd(genomicId, taxId); }); }); Task.WaitAll(readLines, processLines); 

这是我的基准:

在此处输入图像描述

我怀疑在某些处理条件下,生产者/消费者模式可能胜过简单的Parallel.ForEach(File.ReadLines())模式。 但是,它并没有在这种情况下。

在一个线程上读取文件,将其行添加到阻塞队列 。 启动从该队列读取的N任务。 设置队列的最大大小以防止内存不足错误。

就像是:

 public class ParallelReadExample { public static IEnumerable LineGenerator(StreamReader sr) { while ((line = sr.ReadLine()) != null) { yield return line; } } static void Main() { // Display powers of 2 up to the exponent 8: StreamReader sr = new StreamReader("yourfile.txt") Parallel.ForEach(LineGenerator(sr), currentLine => { // Do your thing with currentLine here... } //close lambda expression ); sr.Close(); } } 

认为它会起作用。 (这里没有C#编译器/ IDE)

正如上面提到的@dtb,读取文件然后处理文件中各行的最快方法是:1)将File.ReadAllLines()放入数组中2)使用Parallel.For循环迭代数组。

您可以在此处阅读更多性能基准。

您必须编写的代码的基本要点是:

 string[] AllLines = File.ReadAllLines(fileName); Parallel.For(0, AllLines.Length, x => { DoStuff(AllLines[x]); //whatever you need to do }); 

随着.Net4中更大的arrays大小的引入,只要你有足够的内存,这应该不是问题。

如果要将线程数限制为n ,最简单的方法是使用AsParallel()WithDegreeOfParallelism(n)来限制线程数:

 string filename = "C:\\TEST\\TEST.DATA"; int n = 5; foreach (var line in File.ReadLines(filename).AsParallel().WithDegreeOfParallelism(n)) { // Process line. }