2017-05-10 19 views
0

我剛剛更新到xUnit 2.1。 我使用這種方法通過大量的測試運行在differents程序集中,以使用特定名稱記錄到同一個文件。 問題是我不能管理併發性(即使使用TextWriter.Synchronized),每次我跑我的測試時,不同的測試說:xUnit並在測試時登錄同一文件

的錯誤是:

Message: System.IO.IOException : The process cannot access the file 'C:\LOGS\myFileName-20170510.txt' because it is being used by another process. 

我的方法是:

private static void WriteToLogFile(string fileName, string strMessage) 
     { 
      DateTime utcNow = DateTime.UtcNow; 
      lock (fileName) 
      { 
       using (StreamWriter w = File.AppendText(fileName + utcNow.Year + utcNow.Month.ToString("00") + utcNow.Day.ToString("00") + ".txt")) 
       { 
        w.WriteLine("{0};{1};{2}", DateTime.UtcNow, SecurityHelper.GetPrincipalName(), strMessage); 
        w.Flush(); 
        w.Close(); 
       } 
      } 
     } 

我甚至試過(但是這並沒有幫助):

private static void WriteToLogFile(string fileName, string strMessage) 
{ 
    DateTime utcNow = DateTime.UtcNow; 
    lock (fileName) 
    { 
     using (StreamWriter w = File.AppendText(fileName + utcNow.Year + utcNow.Month.ToString("00") + utcNow.Day.ToString("00") + ".txt")) 
     { 
      w.WriteLine("{0};{1};{2}", DateTime.UtcNow, SecurityHelper.GetPrincipalName(), strMessage); 
      w.Flush(); 
      w.Close(); 
     } 
    } 
} 

private static readonly ConcurrentDictionary<string, object> Tokens = new ConcurrentDictionary<string, object>(); 

private static object GetToken(string fileName) 
{ 
    if (!Tokens.ContainsKey(fileName)) 
     Tokens.TryAdd(fileName, new object()); 
    return Tokens[fileName]; 
} 

這是由於xUnit的一些奇怪行爲? 在此先感謝。

+1

用於寫入日誌文件的方法是用於生產性代碼還是僅用於測試代碼? –

+0

@TheoLenndorff都! – Cirelli94

+0

它不能幫助回答你的問題,但如果你想在將來避免非常,非常非常痛苦......使用記錄器庫而不是滾動自己的記錄器。使用log4net或nlog。即使System.Diagnostic.Trace更好。請。爲了你自己...考慮它,如果可能的話。每當有人使用File.AppendText(或類似的東西)作爲日誌記錄機制時,一隻小貓就會死亡。是的,小貓也因我而死。我只是不想看到更多死去的小貓。死到處都是小貓!他們在跟我說話。他們想要我的靈魂。 NOOOO ...... *理智地踢着*嚴肅。考慮一下。 –

回答

0

行之後是一個問題:

lock (fileName) 

不要使用字符串和參數作爲鎖定對象。在你的情況下嘗試一個私人靜態對象。請參閱MSDNthis question on stackoverflow。這將是這個樣子:

private readonly object Locker = new object(); 

private static void WriteToLogFile(string fileName, string strMessage) 
{ 
    DateTime utcNow = DateTime.UtcNow; 
    lock (Locker) 
    { 
    ... 

這解決了多線程想一次寫的潛在的問題,但這不是真正的問題。看看這個stackoverflow question。我不完全知道xunit測試運行器是如何工作的,但是如果有多個進程一次寫入,你會得到這個異常。除了使用File.AppendText使用(通過計算器問題的答案的建議)的:

using (var stream = File.Open(path, FileMode.Open, FileAccess.Write, FileShare.Read)) 
{ 
} 

操作系統將允許多個進程訪問同一個文件。

您可能仍有以下問題:內容可能很亂,因爲例如兩個進程可能想要在同一行寫入,然後連續轉儲兩個換行符。作爲解決方法,您可以將進程ID附加到日誌文件。

如果這太奇怪,可以考慮使用一個日誌庫來管理這類問題。

+0

儲物櫃應該是私人只讀靜態物體! 非常感謝!最後,因爲我的記錄器需要寫入不同的文件(哪個文件依賴於LogType),我使用了一個字典:''''''''''' '在哪裏LogType是一個枚舉,但我認爲甚至可能是一個字符串。 鎖定時,我做了: 'lock(LockDictionary [logType]){using(...)...}' 謝謝! – Cirelli94

+0

不客氣。字符串可用於鎖定,但不鼓勵它(請參閱http://stackoverflow.com/questions/12804879/is-it-ok-to-use-a-string-as-a-lock-object)。通常使用「對象」。 –