Skip to content

Instantly share code, notes, and snippets.

@crozone
Created July 13, 2023 02:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save crozone/19ceafc4bf2706e77423a54af6d8a5ac to your computer and use it in GitHub Desktop.
Save crozone/19ceafc4bf2706e77423a54af6d8a5ac to your computer and use it in GitHub Desktop.
C# AsyncLock based on SemaphoreSlim
public class AsyncLock
{
private readonly SemaphoreSlim semaphore = new SemaphoreSlim(1, 1);
private readonly Task<IDisposable> releaser;
public AsyncLock()
{
releaser = Task.FromResult((IDisposable)new AsyncLockReleaser(this));
}
public Task<IDisposable> LockAsync(CancellationToken cancellationToken)
{
Task wait = semaphore.WaitAsync(cancellationToken);
return wait.IsCompleted ?
releaser :
wait.ContinueWith(
(_, state) => (IDisposable)state!,
releaser.Result,
CancellationToken.None,
TaskContinuationOptions.ExecuteSynchronously,
TaskScheduler.Default);
}
private sealed class AsyncLockReleaser : IDisposable
{
private readonly AsyncLock toRelease;
internal AsyncLockReleaser(AsyncLock toRelease) {
this.toRelease = toRelease;
}
public void Dispose()
{
toRelease.semaphore.Release();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment