从C#中的多个线程读取同一文件

时间:2009-09-16 01:47:22

标签: c# .net multithreading

我在Google上搜索一些有关此问题的建议,我找到了一些链接。最明显的是this one,但最后我想知道我的代码是如何实现的。

我基本上有两节课。一个是转换器,另一个是 ConverterThread

我创建了一个这个Converter类的实例,它有一个属性ThreadNumber,它告诉我应该同时运行多少个线程(这是从用户读取的),因为这个应用程序将在多CPU系统上使用(物理上,像8 cpu)所以这是假设这将加快导入

Converter实例读取的文件范围从100mb到800mb,此文件的每一行都是制表符分隔的值记录,导入到另一个目标,如数据库。

ConverterThread类只是在线程内部运行(新的Thread(ConverterThread.StartThread))并且有事件通知,因此当它的工作完成时它可以通知Converter类,然后我可以总结所有这些线程的进度并通知用户(例如在GUI中)有关已导入的记录数以及已读取的字节数。

然而,似乎我遇到了一些麻烦,因为我得到关于文件无法读取的随机错误或者进度总和(百分比)超过100%这是不可能的,我认为因为线程管理不善而且事件返回的信息可能格式不正确(因为它从一个线程“传播”到另一个线程),所以会发生这种情况。

您对线程实施的更好实践有什么建议吗?我可以做到这一点吗?

提前致谢。

3 个答案:

答案 0 :(得分:10)

我在一些自己的代码中读取了非常大的文件,我必须告诉你,我对任何声称向读取操作添加线程实际上会提高整体读取性能的说法持怀疑态度。实际上,添加线程实际上可能会通过引起头部搜索来降低性能。很可能这种类型的任何文件操作都是I / O绑定的,而不是CPU绑定的。

鉴于您所引用的帖子的作者从未实际提供过“真实”代码,他声称多个线程将加速I / O仍然是其他人无法测试的。任何通过添加线程来提高硬盘读/写性能的尝试都肯定是I / O绑定的,除非他在读取之间做了一些严重的数字运算,或者偶然发现了一些与磁盘缓存有关的快乐巧合,其中在具有不同硬件特性的另一台机器上,性能改进可能无法实现。

通常,当涉及这种大小的文件时,性能的额外提高20%或30%并不重要,即使可能使用线程,因为这样的任务肯定会被视为后台任务(不是实时的)。我使用多个线程来完成这种工作,不是因为它提高了一个文件的读取性能,而是因为可以在后台同时处理多个文件。

在使用线程执行此操作之前,我仔细对软件进行了基准测试,以确定线程是否会实际提高整体吞吐量。测试结果(在我的开发机器上)是使用与处理器核心数相同数量的线程产生最大可能吞吐量。但那是每个线程处理一个文件。

答案 1 :(得分:10)

一次读取文件的多个线程会遇到麻烦。我将建立一个生产者消费者模型,使生产者读取文件中的行,可能读入缓冲区,然后在完成处理当前工作负载时将它们传递给消费者线程。它确实意味着你有一个阻塞点,线条被分发,但如果处理需要比阅读更长的时间,那么它应该不是那么大的交易。如果阅读是缓慢的部分,那么你真的不需要多个消费者。

答案 2 :(得分:0)

您应该尝试让一个线程读取该文件,因为多个线程可能会被I / O绑定。然后,您可以将这些行提供给一个线程安全的队列,多个线程可以从中将队列出队以解析。

您将无法告知任何一个线程的进度,因为该线程没有明确的工作量。但是,您应该能够通过跟踪已添加到队列中的项目(总数)以及已取出的项目来跟踪大致进度。显然,当您的文件阅读器线程将更多行放入队列时,您的进度似乎会减少,因为有更多行可用,但可能您应该能够比工作人员处理行更快地填充队列。

相关问题