namespace System.Threading { /// /// Provides extension methods for the . /// public static class ReaderWriterLockSlimExtensions { /// /// Acquires a read lock on a lock object that can be released with an /// instance. /// /// The lock object. /// The number of milliseconds to wait, or -1 /// () to wait indefinitely. /// An instance to release the lock. public static IDisposable GetReadLock(this ReaderWriterLockSlim rwLock, int timeoutMilliseconds = -1) { if (!rwLock.TryEnterReadLock(timeoutMilliseconds)) throw new TimeoutException("The read lock could not be acquired."); return new RWLockDisposable(rwLock, 1); } /// /// Acquires a upgradeable read lock on a lock object that can be released with an /// instance. The lock can be upgraded to a write lock temporarily /// with or until the lock is released with /// alone. /// /// The lock object. /// The number of milliseconds to wait, or -1 /// () to wait indefinitely. /// An instance to release the lock. If the lock was /// upgraded to a write lock, that will be released as well. public static IDisposable GetUpgradeableReadLock(this ReaderWriterLockSlim rwLock, int timeoutMilliseconds = -1) { if (!rwLock.TryEnterUpgradeableReadLock(timeoutMilliseconds)) throw new TimeoutException("The upgradeable read lock could not be acquired."); return new RWLockDisposable(rwLock, 2); } /// /// Acquires a write lock on a lock object that can be released with an /// instance. /// /// The lock object. /// The number of milliseconds to wait, or -1 /// () to wait indefinitely. /// An instance to release the lock. public static IDisposable GetWriteLock(this ReaderWriterLockSlim rwLock, int timeoutMilliseconds = -1) { if (!rwLock.TryEnterWriteLock(timeoutMilliseconds)) throw new TimeoutException("The write lock could not be acquired."); return new RWLockDisposable(rwLock, 3); } private struct RWLockDisposable : IDisposable { private readonly ReaderWriterLockSlim rwLock; private int lockMode; public RWLockDisposable(ReaderWriterLockSlim rwLock, int lockMode) { this.rwLock = rwLock; this.lockMode = lockMode; } public void Dispose() { if (lockMode == 1) rwLock.ExitReadLock(); if (lockMode == 2 && rwLock.IsWriteLockHeld) // Upgraded with EnterWriteLock alone rwLock.ExitWriteLock(); if (lockMode == 2) rwLock.ExitUpgradeableReadLock(); if (lockMode == 3) rwLock.ExitWriteLock(); lockMode = 0; } } } }