Why doesn't locking in this code work?

With this code for a very simple registrar:

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 several threads at the same time, I quickly get an error message:

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

Why does blocking not prevent the flow of file access at the same time?

It doesn’t matter if the threads invoke the same instance or different instances in the same file. I also thought that this might be due to some delay in writing files on Windows, but the same thing happens on Linux.

+5
source share
5 answers

You are blocking the time line. You must enter a static object to lock.

+12
source

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

:

. /?

+8

("LogWritter_" + this.FileName)! .

public static readonly object fileLock = new object();

...

lock (fileLock) {
    ...
}

, , .

.NET Framework 4.0, ConcurrentDictionary<TKey, TValue>. Dictionary<TKey, TValue>

public static readonly ConcurrentDictionary<string,object> fileLocks =
    new ConcurrentDictionary<string,object>();

...

object lockObject = fileLocks.GetOrAdd(filename, k => new object());
lock (lockObject) {
    ...
}

UPDATE

,

Object.ReferenceEquals(s1, s2)

string s1 = "Hello";
string s2 = "Hello";
Console.WriteLine(Object.ReferenceEquals(s1, s2)); // ===> true

string s3 = s1 + " World!";
string s4 = s2 + " World!";
Console.WriteLine(s3 == s4); // ===> true
Console.WriteLine(Object.ReferenceEquals(s3, s4)); // ===> false

, , , .. . , , , !

- , .

+4

# , . , , , . , "A" + "B" ; "A" + "B" .

+4

.  string.Concat( "LogWritter_", this.FileName) . , . , ==, Equals() GetHashCode(), , , == Equals() string. ReferenceEquals(), false. , . -, .

class Program
{
    public static void Main(string[] args)
    {
        string locker = "str", temp = "temp";
        string locker1 = locker + temp;
        string locker2 = locker + temp;

        Console.WriteLine("HashCode{0} {1}", locker1.GetHashCode(), locker2.GetHashCode());
        Console.WriteLine("Equals {0}", locker1.Equals(locker2));
        Console.WriteLine("== {0}", locker1 == locker2);
        Console.WriteLine("ReferenceEquals {0}", ReferenceEquals(locker1, locker2));
        app.Program p = new Program();
        Action<string> threadCall = p.Run;
        threadCall.BeginInvoke(locker1, null, null);
        threadCall.BeginInvoke(locker2, null, null);
        Console.Read();
    }

    public void Run(string str)
    {
        lock (str)
        {
            Console.WriteLine("im in");
            Thread.Sleep(4000);
            Console.WriteLine("print from thread id {0}", Thread.CurrentThread.ManagedThreadId);
        }
    }


}
+1

All Articles