iJade iJade - 14 days ago 5
ASP.NET (C#) Question

Will lock prevent the error "The process cannot access the file because it is being used by another process"?

Here is my log writing function:

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);
}
}


But this code sometimes caused me the error:


The process cannot access the file because it is being used by another process


So I modified my code a bit, and here is my new code:

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);
}
}
}


Though I haven't received an error after using this code. But still I just wanted to know if this is correct way to use lock to prevent such errors due to deadlock, and if the way I have used lock is correct or not.

Answer

Your use of lock in your second example won't work properly anyhow because you create a new lock object and lock it every time.

What you really want file wise is something like this:

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();
        }
    }

This should exclusively lock the file while you write BUT properly close off the file once done with.

This does NOT solve the threading issue, because two threads can still collide. If one thread locks the file subsequent requests will fail.

To solve this with a lock, move the lock object to a static that all threads can share and lock against, such as:

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();
            }
        }
    }

}

This will cause subsequent threads to wait until the lock becomes available before writing to the file as originally expected.

Note Oded's comment though, that still applies to this method.

Comments