2014-11-02 49 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