多线程读取和处理大型文本文件
本文关键字:文本 文件 大型 处理 读取 多线程 | 更新日期: 2023-09-27 18:27:09
我有10个超过100Mb的列表,每个列表都有电子邮件,我想用多线程尽可能快地处理它们,而不需要将它们加载到内存中(比如逐行读取或读取小块)
我创建了一个函数,它基于正则表达式删除无效的正则表达式,另一个函数基于每个域将它们组织到其他列表。
我成功地使用了一个线程:while(reader.Peek()!=-1)但这花的时间太长了。
我如何使用多线程(大约100-200),也许还有一个后台工作人员或其他什么东西来在并行处理列表时使用表单
我是csharp:p 的新手
除非数据在多个物理磁盘上,否则任何多个线程都有可能减慢而不是加快进程。
会发生的情况是,你最终会寻找一个地方为一个线程读取数据,然后寻找其他地方为另一个线程读数据,等等,而不是读取连续的数据(相当快)。寻找相对较慢,所以它最终会更慢——通常要慢得多。
你能做的最好的事情就是用一个线程从每个物理磁盘读取数据,然后用另一个线程来处理数据——但除非你的处理非常复杂,或者你有很多快速硬盘,否则一个线程处理可能就足够了。
有多种方法:
1.)您可以像Thread t=new Thread()那样显式地创建线程,但这种方法在创建和管理线程方面代价高昂
2.)您可以使用.net ThreadPool并将执行函数的地址传递给ThreadPool类的QueueUserWorkItem静态方法。这种方法需要一些手动代码管理和同步原语
3.)您可以创建一个System.Threading.Tasks.Task的数组,每个数组都处理一个列表,该列表使用计算机上所有可用的处理器并行执行,并将该数组传递给Task。WaitAll(任务[])等待其完成。这种方法与任务并行性有关,您可以在MSDN 上找到详细信息
Task[] tasks = null;
for(int i = 0 ; i < 10; i++)
{
//automatically create an async task and execute it using ThreadPool's thread
tasks[i] = Task.StartNew([address of function/lambda expression]);
}
try
{
//Wait for all task to complete
Task.WaitAll(tasks);
}
catch (AggregateException ae)
{
//handle aggregate exception here
//it will be raised if one or more task throws exception and all the exceptions from defaulting task get accumulated in this exception object
}
//continue your processing further
您需要了解任务并行库(TPL)。
事实上,这个图书馆是为并行工作而建的。它将以最有效的方式(通常)在线程池上执行您的操作。我唯一要提醒的是,如果你一次运行100-200个线程,那么你可能会遇到不得不处理上下文切换的问题。也就是说,除非您有100-200个处理器。一个好的经验法则是,只并行运行与处理器数量一样多的任务。
其他一些好的资源来审查如何使用TPL:
为什么以及如何使用TPL如何启动任务。
我倾向于使用并行linq(plinq)。
大致如下:
Lists.AsParallel()。SelectMany(列表=>列表)Where(MyItemFileringFunction).GroupBy(DomainExtractionFunction)
AsParallel告诉linq它可以并行地完成这项工作(这意味着后面所有内容的排序将不会被维持)
SelectMany获取您的单个列表并展开它们,以便所有列表中的所有项目都有效地位于单个可枚举中
Where使用谓词函数归档项目
GroupBy按密钥收集它们,其中DomainExtractionFunction是一个从项目(即电子邮件)中获取密钥(在您的情况下是域名)的函数