如何使用多个线程顺序处理大型文本文件内容?

时间:2015-08-03 22:04:00

标签: c# multithreading

我有一个非常大的文本文件,由客户提供,我需要逐行阅读并通过内部系统基于Web的处理系统处理,通过发布请求(一次最多10个线程)。

我知道如何顺序读取文件,但不知道如何启动线程(最多10个)同时处理。我可以一次处理一个,但文件很大,可能需要永远。 任何帮助都会很棒,建议或片段?

3 个答案:

答案 0 :(得分:1)

如果您的大部分工作都是后读处理(因此硬盘访问不是Graffito提到的瓶颈),那么您可能会走上正轨。但是,在同一空间中的线程工作很难正确。如果没有你的代码,很难提出具体的建议。如果你有许多不同的方法可以调用它们并且它们不需要按顺序调用,但它们都需要在你继续前进之前完成,那么你只需要为调用方法中的每个方法创建一个任务,然后你使用Task.WaitAll保存所有内容,直到最后一个任务返回。

另一方面,如果您希望所有任务同时在所有相同的方法中工作,每个任务在不同的文本块上,这可能会更棘手。在这种情况下,为了防止一个线程摆弄字段而另一个线程使用它们,有锁和其他工具使方法更加线程安全。但是,如果您的系统可以处理它,最简单的方法可能是将您想要多线程的所有工作移动到一个单独的类中。那个方法,领域和所有。然后为每个线程创建该类的实例。当thread0或task0在myThreadworkClass [0]里面乱七八糟,而thread1或task1在myThreadworkClass [1]里面时,依此类推,它们将永远不会相遇并相互打架。

所以这取决于您的需求的具体情况,但希望这篇文章能帮助您朝着正确的方向前进。如果您需要更具体的帮助,请发布代码。

答案 1 :(得分:1)

您应该只使用一个线程来打开文件。 File.ReadLines方法逐行读取,而不会立即将整个文件加载到内存中。然后,您可以使用多个线程来处理您读取的数据。 Parallel.ForEach是一个可从.net Framework 4.0获得的选项。

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

使用ParallelOptions.MaxDegreeOfParallelism选项限制最大线程数。

答案 2 :(得分:0)

有一个简单的建议:不要。

逐行读取一个帖子,你将是最快的。如果您使用一个文件多次尝试,您将看到使用多个线程的好处。这是有效的,因为您不是从光盘读取,而是从文件系统缓存中读取。但正如你所说,你有一个非常大的文件

  • 首先不在文件系统缓存中
  • 无论如何都不适合文件系统缓存。

只要您不从raid数组中读取文件,就没有必要使用多个线程。

假设您正在从旋转的硬盘中读取数据,那么吞吐量将减少大约两倍,因为如果您从硬盘的两个不同位置并行读取。盘头需要移动,每次搜索操作需要6-10ms才能移动到新的读取位置。如果你不用寻求,你会更快。

这听起来比实际情况更糟糕。实际上,您的单线程应用程序已经在不知情的情况下使用异步IO。如果从具有默认文件标志(Sequential Scan could be worthwile)的文件中读取,操作系统将在处理字符串时从硬盘中预取数据。在最佳情况下,您的处理需要足够长的时间,以便由于预取数据而立即完成下一个Read操作。

您可以从异步IO中获益,而不会使代码复杂化。通过使用无缓冲的IO可以更快地获得一个内存缓冲区副本,但是为了使其在托管代码中工作,您需要分配HDD扇区大小的页面对齐内存。您需要从HDD中读取它。否则,您的代码将在计算机上失败,例如使用每扇区4KiB的SSD或硬盘。