C# 多线程读取大型txt文件?
我有10万行的大txt文件。 我需要开始n个线程的计数,并从这个文件中为每个线程指定唯一的行C# 多线程读取大型txt文件?,c#,C#,我有10万行的大txt文件。 我需要开始n个线程的计数,并从这个文件中为每个线程指定唯一的行 最好的方法是什么?我想我需要逐行读取文件,迭代器必须是全局的才能锁定它。将文本文件加载到列表将非常耗时,我可以收到OutofMemory异常。有什么想法吗?在一个线程上读取文件,将其行添加到一个线程中。启动从该队列读取的N任务。设置队列以防止内存不足错误。您可以使用逐行读取文件,而无需立即将整个文件加载到内存中,也可以使用并行处理多个线程中的行: Parallel.ForEach(File.ReadLi
最好的方法是什么?我想我需要逐行读取文件,迭代器必须是全局的才能锁定它。将文本文件加载到列表将非常耗时,我可以收到
OutofMemory
异常。有什么想法吗?在一个线程上读取文件,将其行添加到一个线程中。启动从该队列读取的N
任务。设置队列以防止内存不足错误。您可以使用逐行读取文件,而无需立即将整个文件加载到内存中,也可以使用并行处理多个线程中的行:
Parallel.ForEach(File.ReadLines("file.txt"), (line, _, lineNumber) =>
{
// your code here
});
比如:
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)如果要将线程数限制为
n
,最简单的方法是使用aspallel()
和with degreeofparallelism(n)
来限制线程计数:
string filename = "C:\\TEST\\TEST.DATA";
int n = 5;
foreach (var line in File.ReadLines(filename).AsParallel().WithDegreeOfParallelism(n))
{
// Process line.
}
正如上面提到的@dtb,读取文件然后处理文件中的各行的最快方法是: 1) 将文件.ReadAllLines()放入数组中 2) 使用Parallel.For循环在数组上迭代 您必须编写的代码的基本要点是:
string[] AllLines = File.ReadAllLines(fileName);
Parallel.For(0, AllLines.Length, x =>
{
DoStuff(AllLines[x]);
//whatever you need to do
});
在.Net4中引入更大的数组大小后,只要您有足够的内存,这就不应该成为问题。在执行我自己的基准测试后,将61277203行加载到内存中,并将值推入字典/ConcurrentDictionary()中结果似乎支持@dtb上面的答案,即使用以下方法最快:
Parallel.ForEach(File.ReadLines(catalogPath), line =>
{
});
我的测试还显示了以下内容:
var inputLines = new BlockingCollection<string>();
ConcurrentDictionary<int, int> catalog = new ConcurrentDictionary<int, int>();
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);
var inputLines = new BlockingCollection<string>();
ConcurrentDictionary<int, int> catalog = new ConcurrentDictionary<int, int>();
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);
var inputLines=new BlockingCollection();
ConcurrentDictionary目录=新建ConcurrentDictionary();
var readLines=Task.Factory.StartNew(()=>
{
foreach(File.ReadLines(catalogPath)中的var行)
输入行。添加(行);
inputLines.CompleteAdding();
});
var processLines=Task.Factory.StartNew(()=>
{
Parallel.ForEach(inputLines.GetConsumingEnumerable(),line=>
{
string[]lineFields=line.Split('\t');
int genomoid=int.Parse(lineFields[3]);
int-taxId=int.Parse(lineFields[0]);
目录.TryAdd(基因组ID,taxId);
});
});
Task.WaitAll(读取行、处理行);
以下是我的基准:
var inputLines = new BlockingCollection<string>();
ConcurrentDictionary<int, int> catalog = new ConcurrentDictionary<int, int>();
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个随机数,按升序排序,使用
文件。读取行
,在正确的位置获取行并将其传递给线程。您不使用以下方法吗:?使用thr=new Thread[j]重新编写它怎么样;对于(;iFile.ReadLines()
的话,它基本上是一种类似python的生成器,在内部使用Yield?@daantimer我对python一无所知,但是File.ReadLines()只需返回一个IEnumerable,它通过yield
实现。在这种情况下,您的答案可以合并为:是:-)我同意。我只想补充一点,ReadLines enumerable应该被分区。因为每一次并行执行都应该是为了一些重要的事情。可能对SteffenWinkler感兴趣。请注意,第三项在第1项结束后开始,而不是在第2项结束后开始。我不相信你的聚束担忧是正确的。@mjwills-Huh,在进一步的玩弄/测试之后,我不得不同意你的看法。我最初的观察肯定是巧合,否则我没有对发生的事情给予足够的关注。然而,我要注意的一点是Parallel.Foreach似乎将条目列表划分为可用线程的数量,每个线程执行一个子列表。所以线程1得到条目1-20,线程2得到条目21-40,而不是只得到下一个可用条目。如果你不想要这种行为,那就值得一读。也考虑删除你之前的(错误的)评论。嗨,卫国明,谢谢你分享这个基准。虽然我同意必须使用File.ReadLines()
来避免大量内存消耗,但是Parallel.ForEach(File.ReadLines())
真的比单线程处理好吗?流是按顺序设计的,而且硬件一次只支持读取一件东西,因此使用多个线程处理结果可能会增加阻塞和上下文切换的开销;查看简单处理File.Re的结果的性能指标会很有趣