2014-11-02 61 views
0
  1. 我有WCF方法应该创建一些数据的文件。
  2. 此文件有时会被其他系统删除。
  3. 我应该追加现有的文件,如果它存在。
  4. 其他WCF请求不应该丢失数据。

我想过不同的选择,但看起来像我应该在WCF中实现队列。多线程写入WCF请求中的文本文件?

我的想法和尝试:

  1. 使用TextWriter.Synchronized。我发现Synchronized仅适用于它创建的实例。
  2. 每个请求都会创建自己的文件。创建带有最大索引文件的请求应该将所有文件附加到一个文件中。 (不工作时有一定的要求将事情该文件已经是最后一个新的请求将被创建时)
  3. 一些队列WCF(它是如何可能实现?)

测试应用程序(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); 
       } 
      } 

     } 

    } 
} 

PS我无法将此WCF方法设置为同步,因为有些请求会将数据写入其他文件,因此不需要同步它们。

回答

1

您正在创建多个FileStreams,每个任务一个,看起来不正确。即使他们是同步的,他们也不会在他们之间同步,因为他们无法了解其他人。

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

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

+0

提出的代码仅仅是一个例子。真的,我有WCF电话。我不知道谁是第一个和第二个,我会在同一时间接到很多电话。 – Evgeny 2014-11-02 10:04:33

+0

这里的关键是您应该将更多数据传递给每个任务,以便他们可以独立运行并在它们之间同步。 – Eric 2014-11-02 10:24:33

+0

这是不可能的,而在WCF方法中,我没有任何任务。方法WritePartToFile只是模拟服务调用。 – Evgeny 2014-11-02 11:08:40