Skip to content

AsyncLocker

Namespace: ThinkGeo.Core

Provides an asynchronous, keyed locking mechanism that can be used with await.

public static class AsyncLocker

Inheritance ObjectAsyncLocker

Remarks:

This type associates each lock key with a SemaphoreSlim and returns an IDisposable releaser to end the critical section.

Important: The internal lock table is intentionally not pruned. This avoids race conditions that can occur when removing semaphores while other callers are concurrently acquiring the same key. As a result, the number of entries can grow over time.

Use this class only when the set of lock keys is small and stable (for example, a few well-known cache files such as WMTS capabilities). For high-cardinality keys (for example, per-tile file paths), prefer a striped/partitioned locker (e.g., StripedAsyncLocker) to avoid unbounded growth.

Key equality follows ConcurrentDictionary<TKey, TValue> semantics. For strings, keys are compared by value (content), not by reference. You do not need to call String.Intern(String).

Methods

Lock(Object)

Synchronously enters a critical section associated with the specified lock key.

public static IDisposable Lock(object lockObject)

Parameters

lockObject Object

        The object that identifies the critical section. Callers that pass equal keys will be serialized.

Returns

IDisposable

        An  object that releases the lock when disposed.

Exceptions

ArgumentNullException

        Thrown when  is null.

Remarks:

This method blocks the current thread until the lock is acquired. It shares the same underlying semaphore mechanism as AsyncLocker.LockAsync(Object, CancellationToken), ensuring mutual exclusion between synchronous and asynchronous operations on the same key.

Use this method when you need to access a shared resource from a synchronous context (e.g., a non-async method override) while other parts of the application might be accessing it asynchronously.

Typical usage:

using (AsyncLocker.Lock(key))
{
    // Synchronous critical section
}

LockAsync(Object, CancellationToken)

Asynchronously enters a critical section associated with the specified lock key.

public static Task<IDisposable> LockAsync(object lockObject, CancellationToken cancellationToken)

Parameters

lockObject Object

        The lock key that identifies the critical section. Callers that pass equal keys will be serialized.

cancellationToken CancellationToken

        A token that can be used to cancel waiting for the lock.

Returns

Task<IDisposable>

        A task that completes when the lock is acquired. The result is an  that
        must be disposed to release the lock.

Exceptions

ArgumentNullException

        Thrown when  is null.

OperationCanceledException

        Thrown when  is canceled while waiting to acquire the lock.

Remarks:

Typical usage:

using (await AsyncLocker.LockAsync(key, cancellationToken).ConfigureAwait(false))
{
    // protected region
}

This method does not enforce any ordering guarantees beyond per-key mutual exclusion.