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
在每一行启动一个方法。
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
在每一行启动一个方法。