private void ReleaseLock(KeyT name, AsyncLockWithWaiterCount lockEntry, IDisposable lockHandle)
#endif
        {
#if NOASYNC
            Monitor.Exit(lockEntry.LockEntry);
#else
            lockHandle.Dispose();
#endif

            lock (DictionaryAccessMutex)
            //DictionaryAccessMutex.Wait();
            //try
            {
                lockEntry.WaiterCount--;
                Debug.Assert(lockEntry.WaiterCount >= 0);

                if (lockEntry.WaiterCount == 0)   //NB!
                {
                    LockQueueDictionary.Remove(name);
                }
            }
            //finally
            //{
            //    DictionaryAccessMutex.Release();
            //}
        }
            internal LockDictReleaser(KeyT name, AsyncLockWithWaiterCount lockEntry, IDisposable lockHandle, AsyncLockQueueDictionary <KeyT> asyncLockQueueDictionary)
#endif
            {
                this.Name      = name;
                this.LockEntry = lockEntry;
#if !NOASYNC
                this.LockHandle = lockHandle;
#endif
                this.AsyncLockQueueDictionary = asyncLockQueueDictionary;
            }
        public async Task <LockDictReleaser> LockAsync(KeyT name, CancellationToken cancellationToken = default(CancellationToken))
        {
            AsyncLockWithWaiterCount lockEntry;

#pragma warning disable PH_S023     //Message	PH_S023	Using the blocking synchronization mechanics of a monitor inside an async method is discouraged; use SemaphoreSlim instead.
            lock (DictionaryAccessMutex)
#pragma warning restore PH_S023
            //await DictionaryAccessMutex.WaitAsync(cancellationToken);
            //try
            {
                if (!LockQueueDictionary.TryGetValue(name, out lockEntry))
                {
                    lockEntry = new AsyncLockWithWaiterCount();
                    LockQueueDictionary.Add(name, lockEntry);
                }
                else
                {
                    lockEntry.WaiterCount++;  //NB! must be done inside the lock and BEFORE waiting for the lock
                }
            }
            //finally
            //{
            //    DictionaryAccessMutex.Release();
            //}

#if NOASYNC
#pragma warning disable PH_P006  //warning PH_P006 Favor the use of the lock-statement instead of the use of Monitor.Enter when no timeouts are needed.
            Monitor.Enter(lockEntry.LockEntry);
#pragma warning restore PH_P006
            return(new LockDictReleaser(name, lockEntry, this));
#else
            var lockHandle = await lockEntry.LockEntry.LockAsync(cancellationToken);

            return(new LockDictReleaser(name, lockEntry, lockHandle, this));
#endif
        }
 private void ReleaseLock(KeyT name, AsyncLockWithWaiterCount lockEntry)
 internal LockDictReleaser(KeyT name, AsyncLockWithWaiterCount lockEntry, AsyncLockQueueDictionary <KeyT> asyncLockQueueDictionary)