【问题标题】:Concurrency reading writing files并发读写文件
【发布时间】:2012-07-29 07:44:39
【问题描述】:

目前我正在编写 Windows 服务来处理大量 xml 文件并将信息从 xml 文件保存到数据库。有 3 台机器运行指向相同共享位置的相同服务。在这个过程中我总是遇到文件未找到的异常,不知道如何解决这个问题。我试图从目录中获取所有文件并根据机器名称重命名这些文件,并允许每台机器处理它自己的一组文件,但仍然遇到 File Not Found 异常。谁能告诉我处理这个问题的正确方法。

谢谢。

代码

if (Directory.Exists(folder))
{
  string pattern = ".xml";
  string machineName = System.Environment.MachineName;
  string[] files = Directory.GetFiles(folder, pattern, SearchOption.AllDirectories);  
  newExt = string.Format("{0}.{1}", machineName, newExt);
  for (int i = 0; i < files.Length; i++)
  {
      if (files[i].Contains(machineName))
      {
           //replace this new extension
           files[i].Replace(machineName + ".", "");
      }
      else
      {
           files[i] = ChangeExtension(files[i], newExt, true);
      }
  }
  IEnumerable<string> sortedFiles = files.Where(f => !string.IsNullOrEmpty(f) && f.Contains(machineName))
                                         .OrderBy(f => f, Sorter);
}

【问题讨论】:

  • 只是为了排除显而易见的问题...如果服务仅在一台机器上运行,您是否会收到 File Not Found 异常?
  • 如果服务在一台机器上运行无异常,系统工作完美。这个问题是由于两台机器捕获文件的相同快照并同时处理

标签: c# concurrency


【解决方案1】:

如果不查看您的代码,很难看到发生了什么,但我推测这三个单独的服务器会获得一个目录列表,从该列表中选择一个文件来处理,同时另一台服务器已重命名文件,因为 其他 服务器决定开始处理该文件。

如果这种情况很少发生,您可以忽略异常(假设我的解释是正确的)。如果这种情况经常发生,您需要更详细地说明您在做什么。

您可以通过让每台服务器以不同的方式对文件列表进行排序(例如,一个 A-Z、第二个 Z-A、第三个 L-Z、A-J ......),然后在要处理的排序顺序。

【讨论】:

  • 我在上面添加的代码非常简单。 ChangeExtension 简单的重命名文件以追加机器名
  • 正如@eric 所说,您应该忽略异常并继续工作。我猜您重命名文件以将其标记为“正在扫描”,因此让一台机器捕获它而其他机器跳过它的逻辑就可以了。至少对我来说。
【解决方案2】:

请您解释一下目录中文件的名称?

  1. 如果文件的名称中已经包含目标机器名,那么每台机器只处理那些命名的文件就足够了(或者不处理??)。
  2. 如果文件出现时没有指定任何特殊的机器名,这看起来像是工作服务之间的竞争,谁先捕获文件。那么您的异常似乎是可以预料的(正如 Eric J. 所说),您只需尝试..catch 它并省略该文件。这是正常的,其他一些服务已经捕获了该文件。或者你可以考虑一些资源共享技术来避免多个服务同时检查目录。至少你可以创建一些子目录来将所有文件分成一些组,并使每个服务与每个子目录一起工作......

P.S.:当然,如果您觉得我没有发现问题,请您提供一些更准确的信息。

【讨论】:

    【解决方案3】:

    正如 Eric J 提到的,您可以简单地忽略错误:

    if (Directory.Exists(folder))
    {
      string pattern = ".xml";
      string machineName = System.Environment.MachineName;
      string[] files = Directory.GetFiles(folder, pattern, SearchOption.AllDirectories);  
      newExt = string.Format("{0}.{1}", machineName, newExt);
    
      for (int i = 0; i < files.Length; i++)
      {
          try
          {
              if (files[i].Contains(machineName))
              {
                   //replace this new extension
                   files[i].Replace(machineName + ".", "");
              }
              else
              {
                   files[i] = ChangeExtension(files[i], newExt, true);
              }
         catch(FileNotFoundException ex)
         {   
         } 
      }
    
      IEnumerable<string> sortedFiles = files.Where(f => !string.IsNullOrEmpty(f) && f.Contains(machineName))
                                             .OrderBy(f => f, Sorter);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-26
      • 1970-01-01
      • 2016-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多