【问题标题】:Multiple Threads reading from the same file多个线程从同一个文件中读取
【发布时间】:2011-04-01 10:19:13
【问题描述】:

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

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

编辑:该文件大约 18KB 非常小。它被阅读了大约 1,800 次。

谢谢

【问题讨论】:

  • 您的硬盘仍然只有一个磁头,因此您一次只能读取一次。您期望从中获得哪些性能改进?
  • 文件是否适合磁盘缓存?如果是这样,那么多次读取将很快,否则如果文件足够小以适合内存,则使用内存映射文件代替并从中读取。否则,硬盘将花费大量时间抖动而不是执行顺序读取,并且您将失去性能而不是获得它。
  • 硬盘上的一个头?我敢肯定,如今即使是单个盘片驱动器也有多个磁头以及缓存等,可以解决磁头特定的减速问题。
  • @GrayWizardx:错过重点的方法:)
  • @Timwi 猜我做到了。哪一点?我提供了一个替代解决方案来解决多次读取问题。严格指定 FileShare.Read 会修复错误但不会解决问题。

标签: c# xml file foreach parallel-processing


【解决方案1】:

打开文件时需要指定FileShare.Read

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

这样文件可以多次打开阅读

【讨论】:

  • 虽然这是正确的,但除非发布者将文件分成块,否则任何真正的加速都将使用多线程实现是值得怀疑的。
  • @Mitch Wheat:确实如此。但我只是在回答 OP 的问题,而不是判断使用多线程是否是个好主意;)
【解决方案2】:

根据文件的大小和您正在执行的读取类型,首先将文件加载到内存中,然后直接向您的线程提供对其的访问可能会更快。

您没有提供有关文件、读取等的任何细节,所以我不能确定它是否能满足您的特定需求。

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

  1. 加载文件
  2. 对于每个 Xpath 查询,将匹配的节点分派给您的线程。

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

【讨论】:

    【解决方案3】:

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

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

    但是,由于多种原因,您不会因此获得任何加速:

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

    【讨论】:

    • +1 对于“1”和“2”cmets。当多个线程试图读取同一个文件时,FileAccess.Read 和 FileShare.Read 将无法解决问题。所以正如“2”注释中提到的,如果我们只需要阅读它,那么我们可以先阅读一次,然后给多个线程“做处理”。
    • 关于第1点,这不适用于磁盘阵列之类的东西,对于服务器软件来说,这是很容易预料到的。
    【解决方案4】:

    虽然是一篇旧帖子,但它似乎很受欢迎,所以我想我会添加一个解决方案,该解决方案在需要读取文件的多线程环境中效果很好。但是,该文件必须足够小以至少在您的处理期间可以保存在内存中,并且该文件只能在共享访问期间读取而不是写入。

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

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

    【讨论】:

      猜你喜欢
      • 2010-11-28
      • 1970-01-01
      • 1970-01-01
      • 2022-01-05
      • 1970-01-01
      • 2013-08-20
      • 2020-09-05
      • 1970-01-01
      相关资源
      最近更新 更多