Temporary semaphore

I have the following class to control access to a resource:

class Sync : IDisposable
{
    private static readonly SemaphoreSlim Semaphore = new SemaphoreSlim(20);

    private Sync()
    {
    }

    public static async Task<Sync> Acquire()
    {
        await Semaphore.WaitAsync();
        return new Sync();
    }

    public void Dispose()
    {
        Semaphore.Release();
    }
}

Using:

using (await Sync.Acquire())
{
    // use a resource here
}

Now it allows you to use no more than 20 common methods of use.

How to change this class to allow no more than N total uses per unit of time (for example, no more than 20 per second)?

+4
source share
2 answers

20 per second is completely different from 20 at a time. I recommend that you leave thread synchronization behind and use higher-level abstractions that can work more naturally over time as a concept.

, Reactive Extensions .

+3

, Semaphore.Release , ( - . Dispose()), Sync .

class Sync : IDisposable
{
    private static readonly SemaphoreSlim Semaphore = new SemaphoreSlim(20);

    // 0 : semaphore needs to be released.
    // 1 : semaphore already released.
    private int State = 0;

    private Sync()
    {
    }

    // Renamed to conform to Microsoft guidelines.
    public static async Task<Sync> AcquireAsync(TimeSpan releaseAfter)
    {
        var sync = new Sync();

        await Semaphore.WaitAsync().ConfigureAwait(false);

        try
        {
            return sync;
        }
        finally
        {
            // Fire-and-forget, not awaited.
            sync.DelayedRelease(releaseAfter);
        }
    }

    private async void DelayedRelease(TimeSpan releaseAfter)
    {
        await Task.Delay(releaseAfter).ConfigureAwait(false);

        this.ReleaseOnce();
    }

    private void ReleaseOnce()
    {
        // Ensure that we call Semaphore.Release() at most
        // once during the lifetime of this instance -
        // either via DelayedRelease, or via Dispose.
        if (Interlocked.Exchange(ref this.State, 1) == 0)
        {
            Semaphore.Release();
        }
    }

    public void Dispose()
    {
        // Uncomment if you want the ability to
        // release the semaphore via Dispose
        // thus bypassing the throttling.

        //this.ReleaseOnce();
    }
}
0

Source: https://habr.com/ru/post/1545267/


All Articles