/// <summary> /// Attempts to enter the lock with concurrent access where all /// readers can execute concurrently with respect to each other. /// </summary> /// <param name="timeout">The amount of time to wait before timing out.</param> /// <returns>The token used to control the duration of entry.</returns> /// <exception cref="TimeoutException">The lock could not be entered before the <paramref name="timeout"/> expired.</exception> public async Task <IDisposable> TryEnterReadLockAsync(TimeSpan timeout) { LockEntry lockEntry = new LockEntry(); try { Task readerTask = lockEntry.WhenReleased(); // The exclusive lock must be obtained to update the reader list, // but it's also necessary so that the reader will wait on any // writers that entered before it using (await ReaderListLock.TryEnterAsync(timeout).ConfigureAwait(false)) ReaderList.Add(readerTask); // Prevent the reader list from growing indefinitely _ = readerTask.ContinueWith(async _ => { using (await ReaderListLock.EnterAsync().ConfigureAwait(false)) ReaderList.Remove(readerTask); }); return(lockEntry); } catch { // Make sure to dispose the lock entry since // it's not being returned to the caller lockEntry.Dispose(); throw; } }
/// <summary> /// Enters the lock with exclusive access where no other /// readers or writers can execute concurrently with the writer. /// </summary> /// <returns>The token used to control the duration of entry.</returns> public async Task <IDisposable> EnterWriteAsync() { LockEntry lockEntry = new LockEntry(); // The writer must maintain exclusive access until the write operation is complete IDisposable readerListToken = await ReaderListLock.EnterAsync().ConfigureAwait(false); _ = lockEntry.WhenReleased().ContinueWith(_ => readerListToken.Dispose()); await Task.WhenAll(ReaderList).ConfigureAwait(false); ReaderList.Clear(); return(lockEntry); }
/// <summary> /// Enters the lock with concurrent access where all readers /// can execute concurrently with respect to each other. /// </summary> /// <returns>The token used to control the duration of entry.</returns> public async Task <IDisposable> EnterReadAsync() { LockEntry lockEntry = new LockEntry(); Task readerTask = lockEntry.WhenReleased(); // The exclusive lock must be obtained to update the reader list, // but it's also necessary so that the reader will wait on any // writers that entered before it using (await ReaderListLock.EnterAsync().ConfigureAwait(false)) ReaderList.Add(readerTask); // Prevent the reader list from growing indefinitely _ = readerTask.ContinueWith(async _ => { using (await ReaderListLock.EnterAsync().ConfigureAwait(false)) ReaderList.Remove(readerTask); }); return(lockEntry); }