2017-05-10 7 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(または類似のもの)をロギングメカニズムとして使用するたびに、子猫が死ぬ。そしてはい...子猫も私のために死んだ。私はもう死んだ子猫を見たくない。死んだ子猫はどこにでも!彼らは私に話している。彼らは私の魂が欲しい。 NOOO ... *正気がキックする*真剣に。考慮して下さい。 –

答えて

0

は問題です:

lock (fileName) 

ロックオブジェクトとして文字列パラメータを使用しないでください。あなたのケースでは、プライベートな静的オブジェクトを試してみてください。 MSDNおよびthis 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テストランナーがどのように働いているのか正確には分かりませんが、一度に複数のプロセスが記述されている場合は、その例外が発生します。代わりに(stackoverflowの質問の答えにより示唆されるように)File.AppendTextはこれを使用使用する:

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

OSは、同じファイルにアクセスする複数のプロセスを許可します。

あなたはまだ、次の問題がある可能性があります。例えば2つのプロセスが同じ行に記述し、その後、連続して2つの改行をダンプする場合がありますので、内容は、混乱かもしれません。この問題を回避するには、プロセスIDをログファイルに追加することができます。

、これはあまりにも奇妙な取得する場合は、あなたのためにこの種の問題を管理し、ロギングライブラリを使用することを検討してください。ログファイルへの書き込みのためにその方法

+0

ロッカーは 'private readonly static object'ですか? ありがとうございます!私のロガーは(LOGTYPEによって依存するファイル)別のファイルに書き込む必要があるため非常に終わり、私は辞書の使用: 'プライベート静的読み取り専用ConcurrentDictionary LockDictionary =新しいConcurrentDictionary {}; 'LogTypeは列挙型ですが、私は文字列であってもよいと思います。 そして私がロックするとき: 'ロック(LockDictionary [LOGTYPE]){(...)を使用して...} ' ありがとう! – Cirelli94

+0

ようこそ。ストリングはロックに使用できますが、お勧めできません(http://stackoverflow.com/questions/12804879/is-it-ok-to-use-a-string-as-a-lock-objectを参照)。通常は 'オブジェクト'が使われます。 –

関連する問題