C# - 使用 StreamReader 并行化 While 循环导致高 CPU

C# - Parallelizing While Loop with StreamReader causing High CPU

SemaphoreSlim sm = new SemaphoreSlim(10);

using (FileStream fileStream = File.OpenRead("..."))
using (StreamReader streamReader = new StreamReader(fileStream, Encoding.UTF8, true, 4096))
{
    String line;
    while ((line = streamReader.ReadLine()) != null)
    {
        sm.Wait();
        new Thread(() =>
        {
            doSomething(line);
            sm.Release();
        }).Start();
    }
}
MessageBox.Show("This should only show once doSomething() has done its LAST line.");

所以,我有一个非常大的文件,我想在每一行上执行代码。

我想并行执行,但一次最多 10 个。

我的解决方案是使用 SemaphoreSlim 等待并在线程完成时释放。 (由于该功能是同步的,因此 .Release() 的位置有效)。

问题是代码占用了很多CPU。内存按预期运行,而不是加载超过 400mb,它只是每隔几秒上下几 mb。

但是 CPU 变得疯狂,它大部分时间锁定在 100% 并持续 30 秒,然后稍微下降然后返回。

由于我不想将每一行都加载到内存中,并且想 运行 编码,最好的解决方案是什么?

9,700 行文件中有 500 行。

600 行在一个 270 万行的文件中。

编辑

我按照评论中提到的那样从 new Thread(()=>{}).Start(); 更改为 Task.Factory.StartNew(()=>{});,似乎是线程创建和销毁导致了性能下降。而且似乎是对的。在我移动到 Task.Factory.StartNew 后,它 运行 与信号量提到的速度相同,并且它的 CPU 与我的 Parallel.ForEach 代码版本完全一样。

您的代码创建了大量线程,效率低下。 C# 有更简单的方法来处理您的场景。一种方法是:

File.ReadLines(path, Encoding.UTF8)
    .AsParallel().WithDegreeOfParallelism(10)
    .ForAll(doSomething);
  • File.ReadLines不是读取整个文件,而是逐行读取。
  • 使用WithDegreeOfParallelism设置最大并发执行任务数
  • 使用 ForAll 在每一行启动一个方法。