public void CanEnterLocksSync()
        {
            var myLock = new AsyncReaderWriterLockSlim();

            myLock.EnterReadLock();
            Assert.IsTrue(myLock.TryEnterReadLock(0));
            Assert.IsFalse(myLock.TryEnterWriteLock(0));
            myLock.ExitReadLock();
            myLock.ExitReadLock();

            myLock.EnterWriteLock();
            Assert.IsFalse(myLock.TryEnterReadLock(0));
            Assert.IsFalse(myLock.TryEnterWriteLock(0));
            myLock.ExitWriteLock();
        }
        public void DowngradeLockAllowsReadLock()
        {
            var myLock = new AsyncReaderWriterLockSlim();

            myLock.EnterWriteLock();

            Assert.IsFalse(myLock.TryEnterWriteLock(0));
            Assert.IsFalse(myLock.TryEnterReadLock(0));

            // After downgrading the lock and after the try to get the write lock is canceled,
            // it should be possible to enter another read lock.
            myLock.DowngradeWriteLockToReadLock();

            Assert.IsFalse(myLock.TryEnterWriteLock(0));
            Assert.IsTrue(myLock.TryEnterReadLock(0));

            myLock.ExitReadLock();
            myLock.ExitReadLock();
        }
        public void ThrowsOperationCanceledException()
        {
            var myLock = new AsyncReaderWriterLockSlim();

            try
            {
                // Should throw without entering the lock.
                myLock.EnterReadLock(new CancellationToken(true));
            }
            catch (OperationCanceledException)
            {
                // Check that the read lock actually was not entered.
                Assert.IsTrue(myLock.TryEnterWriteLock(0));

                throw;
            }
        }
        public void WaitingReaderIsReleasedAfterWaitingWriterCanceled()
        {
            var myLock = new AsyncReaderWriterLockSlim();

            // Thread A enters a read lock.
            myLock.EnterReadLock();

            // Thread B wants to enter a write lock within 2 seconds. Because Thread A holds
            // a read lock, Thread B will not get the write lock.
            bool threadBResult = true;
            var  threadB       = new Thread(() =>
            {
                bool result = myLock.TryEnterWriteLock(600);
                Volatile.Write(ref threadBResult, result);
            });

            threadB.Start();

            // Wait a bit before starting the next thread, to ensure Thread B is already
            // in the TryEnter...() call.
            Thread.Sleep(200);

            // Thread C wants to enter a read lock. It should get the lock after
            // 2 seconds because Thread B cancels its try to get the write lock after
            // that time.
            var threadC = new Thread(() =>
            {
                myLock.EnterReadLock();
            });

            threadC.Start();

            threadB.Join();
            threadC.Join();

            Assert.IsFalse(Volatile.Read(ref threadBResult));

            myLock.EnterReadLock();
        }