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();
}
}