0

スレッドセーフなメソッドを作成しようとしています。

次のコードで同時実行の問題が発生することはありますか?

このメソッドで同時実行性をテストする方法を見つけることができませんでしたが、私には問題ないようです。どんな助けでも大歓迎です。

   //static locker for thread synchronization
   private static readonly System.Object _object3 = new System.Object();

   //this method needs to be thread-safe
   public static void LogToTextFile(string logMessage, LogLevel logType)
    {
       //make sure only one thread executes this file writing code at a time            
       lock (_object3)
        {
            using (StreamWriter w = File.AppendText(@"c:\logs\log1.txt");
            {
                w.WriteLine("\r\n{0} logged at {1} {2} : {3}", logType.ToString().ToUpper(), DateTime.Now.ToLongTimeString(), DateTime.Now.ToLongDateString(), logMessage);
            }
        }
    }
4

4 に答える 4

3

このコードには同時実行の問題はありません。これは、lock ステートメントによりファイルへの書き込みを 1 つのスレッドのみに許可しているためです。

于 2013-03-09T23:27:56.913 に答える
1

別の、おそらくより良い解決策は、ファイルを開いたままにし、同期を使用TextWriterして書き込みを実行することです。 :TextWriter.Synchronizedの周りにスレッドセーフなラッパーを提供しますTextWriter

返されたラッパーへのすべての書き込み操作はスレッドセーフになります。このメソッドを呼び出して、返されるTextWriterインスタンスで一度に1つのスレッドのみがメソッドを実行できるようにします。

これが簡単な実装です。これはテストされていないことに注意してください。

public static class MyLogger
{
    private static TextWriter s_writer;

    // Not thread-safe. Call this before other threads are allowed to call Log.
    public void Open(string filename) {
        s_writer = TextWriter.Synchronized( File.AppendText(filename) );
    }

    // Also not thread-safe.
    public void Close() {
       s_writer.Dispose();
    }

    // Thread-safe.
    public void Log(string logMessage, LogLevel logType) {
        s_writer.WriteLine("\r\n{0} logged at {1} {2} : {3}",
            logType.ToString().ToUpper(), DateTime.Now.ToLongTimeString(),
            DateTime.Now.ToLongDateString(), logMessage);
    }    
}
于 2013-03-09T23:48:35.110 に答える
1

lock適切にスコープされたオブジェクトを使用していることを考えると、コードに同時実行の問題は見られません。

ただし、コメントに記載されているミリムースのように、潜在的なパフォーマンスの問題があります。2 つのスレッドLogToTextFileが同時にロックしようとすると、一方が最初にロックを取得し、もう一方がブロックされ、ファイルが開かれ、書き込まれ、閉じられます。スレッドの動作によっては、これが受け入れられない場合があります。

私が言及したことが問題である場合は、より複雑なスレッドセーフ ロガーを実装する必要があります。通常、ログ イベントがすぐに書き込まれるキューがあります。次に、定期的にウェイクアップし、ディスク上のファイルへのキューを空にする別のスレッドがあります。キューに対するすべての操作は、ロックを使用して行われます。

于 2013-03-09T23:31:02.883 に答える
1

この特定の関数内に同時実行の問題はありません。このlockステートメントは、内部コードへのアクセスを適切に管理します。

ただし、 へのアクセスには潜在的な並行性の問題がまだあります@"c:\logs\log1.txt"。アプリケーションの別の部分、または同じマシン上の別のプロセスが、コードと同時にファイルに書き込もうとする可能性があります。したがってStreamWriter、このロックがあってもコードが失敗する可能性があります。

この種の同時実行の問題を回避する方法はありません。ファイル システムは、実際に保護する機能がない共有リソースです。代わりに、コードは、ファイル システム アクセスが失敗する可能性があることを受け入れ、その結果を適切に処理する必要があります。

通常、ログ機能を扱うときは、ファイル システムへのアクセスを でラップしtry / catch、発生した例外を飲み込みます。そうしないと、ロギング機能が失敗してアプリケーションがダウンする危険性があります。それはあなたのシナリオでは受け入れられるかもしれませんし、受け入れられないかもしれません。

于 2013-03-10T00:56:09.720 に答える