Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why the lock in this code is not working?

Tags:

c#

locking

With this code for a very basic logger:

lock (string.Concat("LogWritter_", this.FileName))
{
    using (var fileStream = File.Open(this.FileName, FileMode.Append, FileAccess.Write, FileShare.Read))
    {
        using (var w = new StreamWriter(fileStream))
        {
            w.Write(message);
        }
    }
}

when I try it from a few threads simultaneously I quickly get the error:

The process can't access the file because its being used by another file.

Why the lock is not preventing the threads to access the file at the same time?

It doesn't matter if the threads call the same instance or different instances to the same file. Also I thought It could be because of some deferral when writing files in Windows, but on Linux happens the same thing.

like image 746
Santiago Corredoira Avatar asked May 04 '12 17:05

Santiago Corredoira


3 Answers

You are locking on a temporary string. You have to introduce a static object to lock on.

like image 149
empi Avatar answered Oct 03 '22 06:10

empi


Create a Dictionary<string,object> and store your lock objects there with the filepath as key.

A while back, I approached this same question:

Locking by string. Is this safe/sane?

like image 29
spender Avatar answered Oct 03 '22 07:10

spender


The C# lock statement places a lock on the object, not the uniqueness of the string. So, because you are dynamically concatenated two strings, you are essentially creating a new object every single time, so every single lock is unique. Even if you access the same file every time, "A" + "B" results in some new immutable string; "A" + "B" again results in yet another new object.

like image 21
TheBuzzSaw Avatar answered Oct 03 '22 07:10

TheBuzzSaw