Class AdaptiveSemaphore
Defines a semaphore that allows adjusting the concurrency limit at runtime to respond to backpressure.
public sealed class AdaptiveSemaphore : IDisposable
- Inheritance
-
AdaptiveSemaphore
- Implements
- Inherited Members
- Extension Methods
Remarks
This is useful for scenarios where the permitted concurrency should change dynamically, such as reducing parallelism when a downstream service returns rate-limit (429) responses or increasing it when conditions improve.
var semaphore = new AdaptiveSemaphore(initial: 10, minimum: 1, maximum: 20);
// Normal usage - acquire and release a permit.
using (await semaphore.WaitAsync())
{
await httpClient.SendAsync(request);
}
// Reduce concurrency on backpressure.
await semaphore.TryShrinkAsync();
Constructors
AdaptiveSemaphore(int, int, int?)
Initializes a new instance of the AdaptiveSemaphore class.
public AdaptiveSemaphore(int initial, int minimum = 1, int? maximum = null)
Parameters
initialintThe initial number of concurrent permits.
minimumintThe minimum concurrency limit. Defaults to 1.
maximumint?The optional maximum concurrency limit.
Exceptions
- ArgumentOutOfRangeException
Thrown when
minimumis less than 1, ormaximumis less thanminimum.
Properties
Available
Gets the number of permits currently available.
public int Available { get; }
Property Value
Limit
Gets the current concurrency limit.
public int Limit { get; }
Property Value
Methods
Dispose()
Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
public void Dispose()
TryGrow()
Increases the concurrency limit by one by releasing an additional permit.
public int TryGrow()
Returns
- int
The new concurrency limit.
Remarks
If the limit is already at the MADE.Threading.AdaptiveSemaphore.maximum, this method does nothing. This is the inverse of TryShrinkAsync(CancellationToken) and should be called when conditions improve and more concurrency is desirable.
Exceptions
- ObjectDisposedException
Thrown if the semaphore has been disposed.
TryShrinkAsync(CancellationToken)
Reduces the concurrency limit by one by permanently acquiring a permit.
public Task<int> TryShrinkAsync(CancellationToken cancellationToken = default)
Parameters
cancellationTokenCancellationTokenThe cancellation token.
Returns
Remarks
If the limit is already at the MADE.Threading.AdaptiveSemaphore.minimum, this method does nothing. The acquired permit is not released, effectively reducing the pool of available permits.
Exceptions
- ObjectDisposedException
Thrown if the semaphore has been disposed.
Wait(CancellationToken)
Synchronously waits to acquire a permit from the semaphore.
public IDisposable Wait(CancellationToken cancellationToken = default)
Parameters
cancellationTokenCancellationTokenThe cancellation token.
Returns
- IDisposable
An IDisposable that releases the permit when disposed.
Exceptions
- ObjectDisposedException
Thrown if the semaphore has been disposed.
WaitAsync(CancellationToken)
Asynchronously waits to acquire a permit from the semaphore.
public Task<IDisposable> WaitAsync(CancellationToken cancellationToken = default)
Parameters
cancellationTokenCancellationTokenThe cancellation token.
Returns
- Task<IDisposable>
An IDisposable that releases the permit when disposed.
Exceptions
- ObjectDisposedException
Thrown if the semaphore has been disposed.