namespace LLama.Web.Async { /// /// Create an Async locking using statement /// public sealed class AsyncLock { private readonly SemaphoreSlim _semaphore; private readonly Task _releaser; /// /// Initializes a new instance of the class. /// public AsyncLock() { _semaphore = new SemaphoreSlim(1, 1); _releaser = Task.FromResult((IDisposable)new Releaser(this)); } /// /// Locks the using statement asynchronously. /// /// public Task LockAsync() { var wait = _semaphore.WaitAsync(); if (wait.IsCompleted) return _releaser; return wait.ContinueWith((_, state) => (IDisposable)state, _releaser.Result, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); } /// /// IDisposable wrapper class to release the lock on dispose /// /// private sealed class Releaser : IDisposable { private readonly AsyncLock _lockToRelease; internal Releaser(AsyncLock lockToRelease) { _lockToRelease = lockToRelease; } public void Dispose() { _lockToRelease._semaphore.Release(); } } } }