AsyncLock Class
Definition
Provides an asynchronous, non-reentrant mutual-exclusion primitive whose acquisition can be awaited without blocking a thread.
public sealed class AsyncLock : IDisposable
- Inheritance
-
AsyncLock
- Implements
- Inherited Members
- Extension Methods
Examples
private readonly AsyncLock _mutex = new();
public async Task UpdateAsync()
{
using (await _mutex.LockAsync())
{
// Exclusive section; safe to await here.
await SomeOperationAsync();
}
}
Remarks
AsyncLock is the asynchronous analogue of the C# lock statement. Because a held lock may need
to span an await, the lock is acquired with LockAsync() and released by disposing the
AsyncLock.Releaser it returns, typically with a using statement.
The lock owns an explicit FIFO wait queue rather than delegating to SemaphoreSlim. When the lock is free, acquisition completes synchronously and allocates nothing; only a contended acquisition allocates the awaited task. Waiters are granted ownership in strict first-in, first-out order. Each waiter completion source uses RunContinuationsAsynchronously, so the releasing thread never runs a waiter's continuation inline while holding the internal gate.
The lock is not reentrant: a caller that already holds the lock and attempts to acquire it again on the same logical flow will deadlock. Following the package-wide rule, a free lock is acquired even when the supplied token is already canceled; the token only cancels an acquisition that must queue.
Dispose() faults every still-waiting acquisition with ObjectDisposedException and rejects subsequent LockAsync() calls. Disposing is intended for shutdown; dispose only when no further acquisitions are expected. Releasing a holder's AsyncLock.Releaser after disposal is a harmless no-op.
Constructors
AsyncLock()
Initializes a new instance of the AsyncLock class in the released state.
public AsyncLock()
Methods
Dispose()
Releases the resources used by the lock. Any callers still waiting observe an ObjectDisposedException.
public void Dispose()
LockAsync()
Asynchronously acquires the lock.
public ValueTask<AsyncLock.Releaser> LockAsync()
Returns
- ValueTask<AsyncLock.Releaser>
A ValueTask<TResult> that completes once the lock is held, yielding a AsyncLock.Releaser whose disposal releases the lock.
Remarks
The returned ValueTask<TResult> must be awaited exactly once.
Exceptions
- ObjectDisposedException
The lock has been disposed.
LockAsync(CancellationToken)
Asynchronously acquires the lock, observing a cancellation request while waiting.
public ValueTask<AsyncLock.Releaser> LockAsync(CancellationToken cancellationToken)
Parameters
cancellationTokenCancellationTokenA token used to cancel the pending acquisition.
Returns
- ValueTask<AsyncLock.Releaser>
A ValueTask<TResult> that completes once the lock is held, yielding a AsyncLock.Releaser whose disposal releases the lock.
Remarks
The returned ValueTask<TResult> must be awaited exactly once. If the lock is free the result is
produced synchronously and no allocation occurs, even when cancellationToken is already
canceled; otherwise the caller waits until ownership is transferred or the token is canceled.
Exceptions
- ObjectDisposedException
The lock has been disposed.
- OperationCanceledException
cancellationTokenwas canceled before the lock was acquired.
Applies to
| Product | Versions |
|---|---|
| .NET | 8, 10 |