Using a named mutex to lock a file

二次信任 提交于 2019-12-10 03:03:56

问题


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.


回答1:


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:

  • http://msdn.microsoft.com/en-us/library/dd997371.aspx
  • http://blogs.msdn.com/b/csharpfaq/archive/2010/08/12/blocking-collection-and-the-producer-consumer-problem.aspx
  • http://geekswithblogs.net/BlackRabbitCoder/archive/2011/03/03/c.net-little-wonders-concurrentbag-and-blockingcollection.aspx
  • http://www.albahari.com/threading/part5.aspx

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!




回答2:


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



回答3:


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?



来源:https://stackoverflow.com/questions/9077573/using-a-named-mutex-to-lock-a-file

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