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

C# 多个线程从同一文件中读取,c#,xml,file,foreach,parallel-processing,C#,Xml,File,Foreach,Parallel Processing,我有一个需要多次读取的xml文件。我正试图使用Parallel.ForEach来加速这个过程,因为读入的数据与读入顺序无关。数据只是用来填充对象。我的问题是,即使我每次在线程中以只读方式打开文件,它仍会抱怨文件被其他程序打开。(我没有在文本编辑器或任何东西中打开它:)) 如何实现对同一文件的多次读取 编辑:文件大小约为18KB,非常小。它是从大约1800次阅读 谢谢打开文件时,需要指定FileShare。请阅读: using (var stream = new FileStream("theFi

我有一个需要多次读取的xml文件。我正试图使用Parallel.ForEach来加速这个过程,因为读入的数据与读入顺序无关。数据只是用来填充对象。我的问题是,即使我每次在线程中以只读方式打开文件,它仍会抱怨文件被其他程序打开。(我没有在文本编辑器或任何东西中打开它:))

如何实现对同一文件的多次读取

编辑:文件大小约为18KB,非常小。它是从大约1800次阅读


谢谢

打开文件时,需要指定
FileShare。请阅读

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

通过这种方式,可以多次打开文件进行读取,具体取决于文件的大小和正在执行的读取类型。首先将文件加载到内存中,然后让线程直接访问文件可能会更快

你没有提供任何文件的细节,阅读等,所以我不能肯定它是否能满足你的具体需求

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

  • 加载文件
  • 对于每个Xpath查询,将匹配的节点分派给线程

  • 如果线程不直接修改XML,这可能是一种可行的替代方法。

    如果希望多个线程从同一文件中读取,则需要指定
    FileShare.read

    using (var stream = File.Open("theFile.xml", FileMode.Open, FileAccess.Read, FileShare.Read))
    {
        ...
    }
    
    但是,由于多种原因,您无法从中获得任何加速:

  • 您的硬盘一次只能读取一个内容。尽管有多个线程同时运行,但这些线程最终都会互相等待
  • 您无法轻松解析XML文件的一部分。通常每次都必须解析整个XML文件。由于有多个线程一直在读取该文件,因此似乎不希望该文件发生更改。如果是这样的话,那你为什么要读很多遍呢

  • 虽然这是一篇老文章,但它似乎很受欢迎,所以我想我应该添加一个解决方案,对于需要对文件进行读取访问的多线程环境,我已经使用该解决方案取得了很好的效果。但是,该文件必须足够小,至少在处理过程中可以保存在内存中,并且该文件只能在共享访问期间读取,不能写入

    string FileName = "TextFile.txt";
    string[] FileContents = File.ReadAllLines(FileName);
    
    foreach (string strOneLine in FileContents)
    {
      // Do work on each line of the file here
    }
    

    只要文件只被读取,多个线程或程序就可以同时访问和处理它,而不会互相干扰。

    虽然这是正确的,但除非海报将文件划分为块,否则使用多个线程是否会产生任何真正的加速是值得怀疑的。@Mitch Wheat:确实如此。但我只是回答OP的问题,而不是判断使用多线程是否是一个好主意;)你的硬盘仍然只有一个磁头,所以你一次只能读一次。您希望从中获得什么性能改进?文件是否适合磁盘缓存?如果是这样,那么多次读取将很快,否则,如果文件足够小,可以放入内存,则使用内存映射文件,然后从中读取。否则,硬盘将花费大量时间进行抖动,而不是执行顺序读取,并且您将失去性能而不是获得性能。硬盘上的一个磁头?我敢肯定,现在即使是单盘驱动器也有多个磁头,还有缓存等,可以解决磁头特定的慢化问题。@GrayWizardx:错过要点的方法:)@Timwi我想是的。哪一点?我提供了另一种解决方案来解决多重读取问题。严格指定FileShare.Read会修复错误,但不会解决问题。+1表示“1”和“2”注释。当多个线程试图读取同一文件时,FileAccess.Read和FileShare.Read无法解决此问题。因此,正如“2”注释中提到的,如果我们只需要阅读它,那么我们可以先阅读一次,然后对多个线程进行“处理”。关于第1点,这不适用于磁盘阵列之类的东西,对于服务器软件来说,这是很容易想到的。