Using a named mutex to lock a file

心不动则不痛 提交于 2019-12-05 03:28:01

Since you are talking about a producer-consumer situation with multiple threads the "standard solution would be to use BlockingCollection which is part of .NET 4 and up - several links with information:

IF you just want to make the locking process work then:

use a ConcurrentDictionary in combination with the TryAdd method call... if it returns true then the file was not "locked" and is now "locked" so the thread can proceed - and "unlock" it by calling Remove at the end... any other thread gets false in the meantime and can decide what to do...

I would definitely recommend the BlockingCollection approach though!

gabba

I ran into the same problem with many threads that can write in the same file.

The one of the reason that mutex not good because it slowly:

duration of call mutexSyncTest: 00:00:08.9795826    
duration of call NamedLockTest: 00:00:00.2565797

BlockingCollection collection - very good idea, but for my case with rare collisions, parallel writes better than serial writes. Also way with dictionary much more easy to realise.

I use this solution (UPDATED):

public class NamedLock
{
    private class LockAndRefCounter
    {
        public long refCount;
    }

    private ConcurrentDictionary<string, LockAndRefCounter> locksDictionary = new ConcurrentDictionary<string, LockAndRefCounter>();

    public void DoWithLockBy(string key, Action actionWithLock)
    {
        var lockObject = new LockAndRefCounter();

        var keyLock = locksDictionary.GetOrAdd(key, lockObject);
        Interlocked.Increment(ref keyLock.refCount);

        lock (keyLock)
        {
            actionWithLock();

            Interlocked.Decrement(ref keyLock.refCount);
            if (Interlocked.Read(ref keyLock.refCount) <= 0)
            {
                LockAndRefCounter removed;
                locksDictionary.TryRemove(key, out removed);
            }
        }
    }
}
Andreas Niedermair

An alternative would be: make one consumer thread which works on a queue, and blocks if it is empty. You can have several producer threads adding several filepaths to this queue and inform the consumer.

Since .net 4.0 there's a nice new class: System.Collections.Concurrent.BlockingCollection<T>

A while ago I had the same issue here on Stack Overflow - How do I implement my own advanced Producer/Consumer scenario?

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!