多线程写入WCF请求中的文本文件?

时间:2014-11-02 09:40:20

标签: c# .net multithreading file-io .net-4.5

  1. 我有WCF方法,它应该用一些数据创建文件。
  2. 此文件有时会被其他系统删除。
  3. 我应该附加现有文件(如果存在)。
  4. 其他WCF请求不应丢失数据。
  5. 我考虑过不同的选项,但看起来我应该在WCF中实现队列。

    我的想法和尝试:

    1. 使用了TextWriter.Synchronized。我发现Synchronized仅适用于创建它的实例。
    2. 每个请求都会创建自己的文件。使用max index创建文件的请求应将所有文件追加到一个文件中。 (当某个请求将文件已经是最后一个新请求时,将无法正常工作)
    3. WCF中的某些队列(如何实现?)
    4. 测试应用程序(模拟WCF方法WritePartToFile):

      class Program
      {
          private static string FileFormat = "file{0}.1001";
          static void Main(string[] args)
          {
              int countOfLines = 100;
              var processesCount = 200;
      
              var files = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.1001");
              foreach (var file in files)
              {
                  File.Delete(file);
              }
      
              var expectedFilesCount = processesCount * countOfLines;
              Console.WriteLine("Trying to write. Processes:" + processesCount.ToString() + ". Lines:" + countOfLines + ". Expected lines:" + processesCount * countOfLines);
              var tasks = new List<Task>();
              for (int i = 1; i < processesCount; i++)
              {
                  var result = Task.Factory.StartNew(() =>
                  {
                      WritePartToFile("Task:" + i.ToString(), countOfLines);
                  });
      
                  tasks.Add(result);
              }
      
              Console.WriteLine("Wait...");
              Task.WaitAll(tasks.ToArray());
      
              var fileName = string.Format(FileFormat, "");
              var lines = 0;
              if (File.Exists(fileName))
              {
                  lines = File.ReadLines(fileName).Count();
              }
      
              if (lines != expectedFilesCount)
              {
                  Console.WriteLine("Error!!! Total lines  (" + lines + ") != expected (" + expectedFilesCount + ")");
              }
      
              Console.WriteLine("Done. Lines added:" + lines + " Any key to exit.");
              Console.Read();
          }
      
          public static void WritePartToFile(string taskName, int countOfLines)
          {
              // Find free file name.
              var fileName = string.Format(FileFormat, "temp_1");
      
              int fileIndex = 1;
              while (File.Exists(fileName))
              {
                  fileIndex++;
                  fileName = string.Format(FileFormat, "temp_" + fileIndex);
              }
      
              var logFileStream = new FileStream(fileName, FileMode.Append, FileAccess.Write, FileShare.Read);
              using (var myWriter = new StreamWriter(logFileStream))
              {
                  for (int i = 1; i < countOfLines; i++)
                  {
                      myWriter.WriteLine(taskName + ". Line number: " + i.ToString() + ". Guid:" + Guid.NewGuid().ToString());
                  }
              }
      
              // Check is current file has MAX index (next index doesnot exists). Merge items (doesnot working)
              var nextFile = string.Format(FileFormat, "temp_" + fileIndex + 1);
              if (!File.Exists(nextFile))
              {
                  var destinationFileName = string.Format(FileFormat, "");
      
                  var mergedLines = new List<string>();
                  // Merge all files into destination.
                  var files = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.1001");
                  foreach (var file in files)
                  {
                      if (File.Exists(file))
                      {
                          mergedLines.AddRange(File.ReadAllLines(file));
                      }
                  }
      
                  logFileStream = new FileStream(destinationFileName, FileMode.Append, FileAccess.Write, FileShare.None);
                  using (var myWriter = new StreamWriter(logFileStream))
                  {
                      foreach (var item in mergedLines)
                      {
                          myWriter.WriteLine(item);
                      }
                  }
      
              }
      
          }
      }
      

      P.S。我无法将此WCF方法设置为同步,因为某些请求会将数据写入其他文件,因此不需要同步。

1 个答案:

答案 0 :(得分:1)

您正在创建多个FileStream,每个任务一个,这似乎不正确。即使它们是同步的,它们也不会在它们之间同步,因为它们无法了解其他的。

您需要做的是在main中创建文件处理程序,然后将其传递给您的任务。然后每个任务都会尝试写入同一个FileStream。由于您要求系统的其他部分可以访问此文件,因此您无法始终保持打开状态。

创建一个包含文件处理的新类。该类将处理与适当锁定的同步。然后创建它的一个实例并将其传递给您的任务,这样所有Task都将拥有对该文件的单一共享访问权限。在该类中,您可以添加逻辑以检查它是否存在,打开文件并立即关闭它