Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 定时信号量_C#_.net_Synchronization_Semaphore - Fatal编程技术网

C# 定时信号量

C# 定时信号量,c#,.net,synchronization,semaphore,C#,.net,Synchronization,Semaphore,我有以下类来管理对资源的访问: class Sync : IDisposable { private static readonly SemaphoreSlim Semaphore = new SemaphoreSlim(20); private Sync() { } public static async Task<Sync> Acquire() { await Semaphore.WaitAsync();

我有以下类来管理对资源的访问:

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();
    }
}
现在它允许不超过20个共享使用

如何修改该类以允许每单位时间内不超过N次共享使用(例如,不超过每秒20次)?

“每秒20次”与“每次20次”完全不同。我建议您将线程同步抛在脑后,使用更高级别的抽象,能够更自然地处理时间


特别是,它有许多不同的节流运算符。

这里有一个基本的重新实现,它在指定的时间段结束时调用
信号量。释放
,或者在
同步
实例被释放时(可选-请参阅
Dispose()
中的代码注释)

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's 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();
    }
}
类同步:IDisposable
{
私有静态只读信号量slim信号量=新信号量slim(20);
//0:需要释放信号量。
//1:信号量已释放。
私有int状态=0;
专用同步()
{
}
//重命名为符合Microsoft的指导原则。
公共静态异步任务AcquireAsync(TimeSpan releaseAfter)
{
var sync=新同步();
wait Semaphore.WaitAsync().ConfigureWait(false);
尝试
{
返回同步;
}
最后
{
//火和遗忘,不是等待。
sync.DelayedRelease(releaseAfter);
}
}
专用异步void DelayedRelease(TimeSpan releaseAfter)
{
等待任务。延迟(releaseAfter)。配置等待(false);
这个。ReleaseOnce();
}
私有void ReleaseOnce()
{
//确保我们最多调用Semaphore.Release()
//在该实例的生存期内执行一次-
//通过DelayedRelease或Dispose。
if(联锁交换(参考此状态,1)==0)
{
Semaphore.Release();
}
}
公共空间处置()
{
//如果您希望能够
//通过Dispose释放信号量
//从而绕过节流阀。
//这个。ReleaseOnce();
}
}

您能否
获取
然后在其他线程中使用资源?如果是这样,您可以让主线程等待固定的时间,然后释放信号量。只是想一想,这可能会给出一个想法:
可观察。Throttle
将丢失请求。您可以尝试
Observable.CombineLatest(requestObservable,Observable.Timer(TimeSpan.FromMiliseconds(100)),(x,)=>x)。订阅(DoSomething)
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's 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();
    }
}