-
-
Notifications
You must be signed in to change notification settings - Fork 371
Open
Description
I know there has been a couple issues about this, but I wanted to chime in on the topic. The code to do this properly and efficiently isn't exactly straightforward, so I think it would be a valuable addition. I had to add this to my project:
public static IDisposable Lock(this AsyncLock asyncLock, TimeSpan timeout, CancellationToken cancellationToken = default)
{
if (timeout == Timeout.InfiniteTimeSpan)
return asyncLock.Lock(cancellationToken);
if (timeout == TimeSpan.Zero)
{
try
{
return asyncLock.Lock(new CancellationToken(true));
}
catch (OperationCanceledException)
{
throw new TimeoutException("Failed to acquire lock immediately.");
}
}
using var timeoutCts = new CancellationTokenSource(timeout);
using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutCts.Token);
try
{
return asyncLock.Lock(linkedCts.Token);
}
catch (OperationCanceledException) when (timeoutCts.IsCancellationRequested)
{
throw new TimeoutException("Failed to acquire lock within the specified timeout.");
}
}
public static AwaitableDisposable<IDisposable> LockAsync(this AsyncLock asyncLock, TimeSpan timeout, CancellationToken cancellationToken = default)
{
return new(Impl(asyncLock, timeout, cancellationToken));
static async Task<IDisposable> Impl(AsyncLock asyncLock, TimeSpan timeout, CancellationToken cancellationToken)
{
if (timeout == Timeout.InfiniteTimeSpan)
return await asyncLock.LockAsync(cancellationToken);
if (timeout == TimeSpan.Zero)
{
try
{
return await asyncLock.LockAsync(new CancellationToken(true));
}
catch (OperationCanceledException)
{
throw new TimeoutException("Failed to acquire lock immediately.");
}
}
using var timeoutCts = new CancellationTokenSource(timeout);
using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutCts.Token);
try
{
return await asyncLock.LockAsync(linkedCts.Token);
}
catch (OperationCanceledException) when (timeoutCts.IsCancellationRequested)
{
throw new TimeoutException("Failed to acquire lock within the specified timeout.");
}
}
}Metadata
Metadata
Assignees
Labels
No labels