Skip to content

thomhurst/AsyncSemaphore

Repository files navigation

AsyncSemaphore

A simple wrapper around a SemaphoreSlim featuring:

  • Automatic releasing without try/finally blocks by utilising the IDisposable using pattern
  • Guarantee that release can only be called once per WaitAsync call
  • Analyzers to help you implement the desired pattern
  • An IAsyncSemaphore interface for if you need to mock

Install

dotnet add package AsyncSemaphore

Usage

private readonly AsyncSemaphore _asyncSemaphore = new AsyncSemaphore(1);

public async Task MyMethod()
{
    // Just assign the `IDisposable` returned from `WaitAsync` to a variable and use the using statement with it
    using var lockHandle = await _asyncSemaphore.WaitAsync();

    // Do whatever you want - Even if we throw exceptions, we'll release the semaphore once we leave this method's scope
    await DoSomethingInsideLock();
}

or scoped:

private readonly AsyncSemaphore _asyncSemaphore = new AsyncSemaphore(1);

public async Task MyMethod()
{
    // or create your own scope with {} braces - And after you leave that scope, your lock will be released
    using (await _asyncSemaphore.WaitAsync())
    {
        await DoSomethingInsideLock();
    }

    await DoSomethingAfterLockReleased();
}

Benchmarks and allocations can be seen below.

BenchmarkDotNet v0.13.12, Windows 11 (10.0.22621.3593/22H2/2022Update/SunValley2)
11th Gen Intel Core i7-1185G7 3.00GHz, 1 CPU, 8 logical and 4 physical cores
.NET SDK 8.0.106
  [Host]     : .NET 8.0.6 (8.0.624.26715), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
  DefaultJob : .NET 8.0.6 (8.0.624.26715), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
Method Mean Error StdDev Allocated
Raw_Semaphore_Slim 38.89 ns 0.622 ns 0.519 ns -
AsyncSemaphore_With_Inherited_Scope 51.36 ns 0.466 ns 0.413 ns -
AsyncSemaphore_With_Braced_Scope 51.04 ns 0.274 ns 0.243 ns -

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages