并发读写文件

时间:2012-07-26 23:13:12

标签: c# concurrency

目前我正在编写Windows服务来处理大量xml文件并将信息从xml文件保存到数据库。有3台运行相同服务的计算机指向相同的共享位置。在这个过程中,我总是遇到异常,即File Not Found,并且不知道如何解决这个问题。我试图从目录中获取所有文件并根据计算机名重命名这些文件,并允许每台计算机处理它自己的文件集,但仍然遇到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);
}

3 个答案:

答案 0 :(得分:1)

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

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

您可以通过让每个服务器以不同的方式对文件列表进行排序(例如,一个AZ,第二个ZA,第三个LZ,AJ,...)来最小化对同一文件的争用,然后选择排序顺序。

答案 1 :(得分:0)

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

  1. 如果文件的名称中已经有目标机器名,那么每台机器只处理那些命名文件(或不是??)就足够了。
  2. 如果出现的文件没有指定任何特殊的机器名,则它看起来像是工作服务中的竞争对手,他们首先捕获文件。然后你的异常似乎是可以预料的(就像Eric J.所说的那样),你只需要尝试..抓住它并省略文件。它是normall,其他一些服务已经捕获了该文件。或者您可以考虑一些资源共享技术,以避免多次服务一次检查目录。至少你可以制作一些子目录来将所有文件划分为一些组,并使每个服务与每个子目录一起工作......
  3. P.S。:当然,如果您觉得我未能发现问题,请您提供更准确的信息。

答案 2 :(得分:0)

正如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);
}