2010-08-19 106 views
10

我有一个xml文件,需要从很多次读取。我正在尝试使用Parallel.ForEach来加速这个过程,因为没有读入的数据与它读取的顺序有关。数据只是用来填充对象。我的问题是即使我每次在线程中打开文件为只读,但它抱怨说它是由另一个程序打开的。 (我没有在文本编辑器中打开它或任何东西:))从同一文件读取多个线程

如何从同一个文件中完成多次读取?

编辑:该文件是〜18KB很小。它从大约1800次读取。

感谢

+4

您的硬盘驱动器仍然只有一个磁头,因此您一次只能读一个磁头。你期望从中获得哪些性能提升? – Daniel 2010-08-20 00:05:08

+1

该文件适合磁盘缓存吗?如果是这样,那么多个读取将会很快,否则如果该文件足够小以适应内存,则改为使用内存映射文件并从中读取。否则,硬盘将花费大量时间进行颠簸而不是执行顺序读取,您将失去性能而不是获得它。 – mdma 2010-08-20 00:08:05

+1

硬盘上的一个磁头?我非常确定,即使是单碟硬盘,现在还有多个磁头,以及缓存等,这些解决方案能够解决头部特定的减速问题。 – GrayWizardx 2010-08-20 00:09:56

回答

24

如果你想多线程从同一个文件中读取,你需要指定FileShare.Read

using (var stream = File.Open("theFile.xml", FileMode.Open, FileAccess.Read, FileShare.Read)) 
{ 
    ... 
} 

然而,就不会实现任何与此加速,出于多种原因:

  1. 您的硬盘一次只能读取一件东西。虽然您有多个线程同时运行,但这些线程最终都会等待对方。
  2. 您无法轻松解析XML文件的一部分。您通常必须每次解析整个XML文件。由于您有多个线程一直在阅读它,因此您似乎并不期望文件发生更改。如果是这样的话,那么为什么你需要多次阅读它?
+0

+1对于“1”和“2”评论。当多个线程试图读取同一文件时,FileAccess.Read和FileShare.Read不会解决问题。正如在“2”注释中提到的,如果我们只需要读取它,那么我们可以先读一遍,然后给出多线程的“处理”。 – Vytas999 2016-02-25 10:08:10

+0

关于第1点,这不适用于像磁盘阵列这样的服务器软件,这很容易理解。 – Matt 2018-03-04 18:28:58

1

当你打开文件,你需要指定FileShare.Read

using (var stream = new FileStream("theFile.xml", FileMode.Open, FileAccess.Read, FileShare.Read)) 
{ 
    ... 
} 

这样的文件可以读取

+4

虽然这是正确的,除非海报将文件分割成块,但可疑的是,使用多线程会发生任何真正的加速。 – 2010-08-20 00:03:23

+3

@米奇小麦:的确如此。但我只是回答OP的问题,而不是判断是否使用多线程是一个好主意;) – 2010-08-20 00:14:41

+1

教一个人钓鱼和所有的...... – 2010-08-20 01:13:38

3

根据文件的大小来多次打开并且您正在执行的读取操作的类型可能会首先将文件加载到内存中,然后直接向您的线程提供对其的访问。

你没有提供关于文件,读取等任何细节,所以我不能确定它是否会解决您的具体需求。

一般的前提是在单个线程中加载文件一次,然后直接(通过Xml结构)或间接(通过XmlNodes等)为每个线程提供对文件的访问权限。我设想类似于:

  1. 加载文件
  2. 对于每个Xpath查询调度匹配的节点到你的线程。

如果线程不直接修改XML,这可能是一个可行的选择。

+0

我会尝试加载到内存中,感谢您的想法。 – Pieces 2010-08-20 00:30:10