I'm using a named mutex to lock access to a file (with path 'strFilePath') in a construction like this:
private void DoSomethingsWithAFile(string strFilePath)
{
Mutex mutex = new Mutex(false,strFilePath.Replace("\\",""));
try
{
mutex.WaitOne();
//do something with the file....
}
catch(Exception ex)
{
//handle exception
}
finally
{
mutex.ReleaseMutex();
}
}
So, this way the code will only block the thread when the same file is being processed already. Well, I tested this and seemed to work okay, but I really would like to know your thoughts about this.
The use of mutex locks is very easy. First, we need to declare a lock variable of type Mutex. Second, before entering the critical section that is protected by that lock, execute the Lock() method of that lock. Third, before exiting the critical section, execute the Unlock() method of the lock.
Named mutex objects are used for inter-process synchronization because multiple applications can access the same mutex object. The mutex class is designed to protect a shared resource like memory, file handle or network connection from simultaneous access by multiple threads or processes.
Mutex only locks a thread. It does not lock a resource. You can still access it via direct memory manipulation.
If the mutex is already locked by another thread, the thread waits for the mutex to become available. The thread that has locked a mutex becomes its current owner and remains the owner until the same thread has unlocked it.
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!
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);
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With