9

これが私のログ書き込み機能です:

public static void WriteLog(string source, string message)
{
    string logFilePath = @"C:\LogFile\log.txt";
    using (StreamWriter sw = new StreamWriter(logFilePath, true))
    {
        sw.Write(source + ": :" + message);
    }
}

しかし、このコードは時々私にエラーを引き起こしました:

別のプロセスによって使用されているため、プロセスはファイルにアクセスできません

そこで、コードを少し変更しました。新しいコードは次のとおりです。

public static void WriteLog(string source, string message)
{
    object _lock = new object();
    lock (_lock)
    {
        string logFilePath = @"C:\LogFile\log.txt";
        using (StreamWriter sw = new StreamWriter(logFilePath, true))
        {
            sw.Write(source + ": :" + message);
        }
    }
}

このコードを使用した後、エラーは発生していませんが。しかし、それでも私は、これがデッドロックによるそのようなエラーを防ぐためにロックを使用する正しい方法であるかどうか、そして私がロックを使用した方法が正しいかどうかを知りたいと思っていました。

4

2 に答える 2

26

2番目の例でのロックの使用は、新しいロックオブジェクトを作成して毎回ロックするため、とにかく正しく機能しません。

ファイルに関して本当に必要なのは、次のようなものです。

public static void WriteLog(string source, string message)
    {
        string logFilePath = @"C:\LogFile\log.txt";

        using (FileStream file = new FileStream(logFilePath,FileMode.Append,FileAccess.Write,FileShare.None)) 
        {
            StreamWriter writer = new StreamWriter(file);

            writer.write(source + ": : " + message);

            file.Flush();
            file.Close();
        }
    }

これにより、書き込み中はファイルが排他的にロックされますが、完了したらファイルを適切に閉じてください。

2つのスレッドがまだ衝突する可能性があるため、これはスレッドの問題を解決しません。1つのスレッドがファイルをロックすると、後続の要求は失敗します。

これをロックで解決するには、ロックオブジェクトを、すべてのスレッドが共有およびロックできる静的オブジェクトに移動します。たとえば、次のようになります。

public static class Logger
{

    private static object locker = new object();

    public static void Log(string source, string message)
    {
        lock (locker) 
        {
            string logFilePath = @"C:\LogFile\log.txt";

            using (FileStream file = new FileStream(logFilePath,FileMode.Append,FileAccess.Write,FileShare.None)) 
            {
                StreamWriter writer = new StreamWriter(file);

                writer.write(source + ": : " + message);   
                writer.Flush();

                file.Close();
            }
        }
    }

}

これにより、後続のスレッドは、当初の予想どおりにファイルに書き込む前に、ロックが使用可能になるまで待機します。

ただし、Odedのコメントに注意してください。これは、このメソッドにも当てはまります。

于 2012-09-04T19:21:08.427 に答える
2

log4netまたはEnterpriseLibraryのLoggingApplicationBlockを使用します。彼らはすでにファイルへの書き込みをバッファリングしているので、それは確かにあなたを助けるでしょう。

あなたはインターネット上でたくさんのサンプルを見つけることができます。

于 2012-09-04T19:22:55.450 に答える