多线程读取和处理大型文本文件

时间:2012-03-09 05:02:23

标签: c# multithreading asynchronous backgroundworker large-files

我有10个超过100Mb的列表,每个都有电子邮件,我想尽可能快地使用多线程处理它们而不将它们加载到内存中(比如逐行读取或读取小块)

我创建了一个函数,它根据正则表达式删除无效的函数,另一个函数根据每个域将其组织到其他列表。

我设法使用一个线程: while(reader.Peek()!= -1) 但它太长了。

如何在并行处理列表时使用多线程(大约100 - 200)和背景工作者或某些东西来使用表单?

我是csharp的新手:P

4 个答案:

答案 0 :(得分:5)

除非数据位于多个物理光盘上,否则任何多个线程都可能会减慢而不是加速该过程。

除了读取连续数据(非常快)之外,你最终会寻找一个地方来读取一个线程的数据,然后寻找其他地方来读取另一个线程的数据,等等。寻求相对较慢,因此结果较慢 - 通常慢得多。

关于你可以做的最好的事情是将一个线程专用于从每个物理磁盘读取数据,然后用另一个线程来处理数据 - 但除非你的处理非常复杂,或者你有很多快速硬盘,一个线程用于处理可能完全足够。

答案 1 :(得分:2)

有多种方法:

1。)您可以像Thread t = new Thread()一样显式创建线程,但这种方法在创建和管理线程时很昂贵。
2.)您可以使用.net ThreadPool并将执行函数的地址传递给ThreadPool类的QueueUserWorkItem静态方法。这种方法需要一些手动代码管理和同步原语 3.)您可以创建一个System.Threading.Tasks.Task数组,每个处理一个列表,使用计算机上所有可用的处理器并行执行,并将该数组传递给task.WaitAll(Task [])等待它们完成。此方法与任务并行有关,您可以在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

答案 2 :(得分:1)

您需要查看Task Parallel Library (TPL)

实际上,这个库是为并行工作而制作的。它将以最有效的方式(通常)在Threadpool上执行您的操作。我唯一要注意的是,如果你一次运行100-200个线程,那么你可能会遇到必须处理上下文切换的问题。也就是说,除非你有100-200个处理器。一个好的经验法则是只运行与处理器并行的任意数量的任务。

审查如何使用TPL的其他一些好资源:

Why and how to use the TPL How to start a task.

答案 3 :(得分:0)

我倾向于使用并行linq(plinq)。

有些事情:

Lists.AsParallel()    .SelectMany(list =&gt; list)    。凡(MyItemFileringFunction)    .GroupBy(DomainExtractionFunction)

AsParallel告诉linq它可以并行执行此操作(这意味着不会维护以下所有内容的顺序)

SelectMany获取您的个人列表并展开它们,以便所有列表中的所有项目都有效地存储在单个Enumerable中

使用谓词函数提交项目的位置

GroupBy通过密钥收集它们,其中DomainExtractionFunction是从项目(即电子邮件)获取密钥(您的案例中的域名)的函数