Why is there no Monitor.EnterAsync-like method

Viewed 5609

I see many methods across new framework that uses new asynchronous pattern/language support for async/await in C#. Why is there no Monitor.EnterAsync() or other async lock mechanism that releases current thread & returns as soon as lock is available?

I assume that this is not possible - question is why?

5 Answers

This worked well for me as detailed here: SemaphoreSlim Class


Semaphores are of two types: local semaphores and named system semaphores.

The former is local to an app. The latter is visible throughout the operating system and is suitable for inter-process synchronization.

The SemaphoreSlim is a lightweight alternative to the Semaphore class that doesn't use Windows kernel semaphores. Unlike the Semaphore class, the SemaphoreSlim class doesn't support named system semaphores.

You can use it as a local semaphore only. The SemaphoreSlim class is the recommended semaphore for synchronization within a single app.

public class ResourceLocker
{
   private Dictionary<string, SemaphoreSlim> _lockers = null;

   private object lockObj = new object();

   public ResourceLocker()
   {
      _lockers = new Dictionary<string, SemaphoreSlim>();
   }

   public SemaphoreSlim GetOrCreateLocker(string resource)
   {
       lock (lockObj)
       {
          if (!_lockers.ContainsKey(resource))
          {
             _lockers.Add(resource, new SemaphoreSlim(1, 1));
          }

             return _lockers?[resource];
        }
    }

    public bool ReleaseLocker(string resource)
    {
       lock (lockObj)
       {
         if (_lockers.ContainsKey(resource))
         {
           var locker = _lockers?[resource];

           if (locker != null)
           {
             locker.Release();

             return true;
            }

             _lockers.Remove(resource);
          }
          return false;
        }//lock
      }
 }

Usage

var resource = "customResource";
var someObject = new SomeObject();
SomeResponse response = null;
var resourceLocker = new ResourceLocker();
try
  {
    var semaSlim = resourceLocker.GetOrCreateLocker(resource);

    semaSlim.Wait();     

    response = someObject.DoSomething();
   }
   finally
   {
     resourceLocker.ReleaseLocker(resource);
   }     

Async

   Task.Run(async ()=>{
        var semaSlim = resourceLocker.GetOrCreateLocker(resource);

        await semaSlim.WaitAsync();     

        response = someObject.DoSomething();

        resourceLocker.ReleaseLocker(resource);
    });
Related