| File: Utils\AsyncLock.cs | Web Access |
| Project: src\src\Aspire.Dashboard\Aspire.Dashboard.csproj (Aspire.Dashboard) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. namespace Aspire.Dashboard.Utils; /// <summary> /// Provides mutual exclusion with asynchronous lock acquisition. /// </summary> internal sealed class AsyncLock { private readonly SemaphoreSlim _semaphore = new(1, 1); /// <summary> /// Acquires the lock synchronously. /// </summary> /// <returns>A handle that releases the lock when disposed.</returns> public IDisposable Lock() { _semaphore.Wait(); return new Releaser(_semaphore); } /// <summary> /// Acquires the lock asynchronously. /// </summary> /// <param name="cancellationToken">The token to monitor for cancellation requests.</param> /// <returns>A handle that releases the lock when disposed.</returns> public async ValueTask<IDisposable> LockAsync(CancellationToken cancellationToken = default) { await _semaphore.WaitAsync(cancellationToken).ConfigureAwait(false); return new Releaser(_semaphore); } private sealed class Releaser(SemaphoreSlim semaphore) : IDisposable { private SemaphoreSlim? _semaphore = semaphore; public void Dispose() { Interlocked.Exchange(ref _semaphore, null)?.Release(); } } }