使用.Net 4.0 / 4.5任务时,如何实现有效的速率限制算法(每个时间间隔执行某个操作的N次)?例如,如果超过N条消息在一秒内发送,我希望SendMessageAsync
阻止(不发送另一条消息)。
await Task.WhenAll(
Enumerable.Range(0, TOTAL_MESSAGES)
.Select(async x =>
{
await clientSession.SendMessageAsync(CreateMessage());
}));
我已尝试在Task.Delay
内使用SendMessageAsync
,但由于等待Task.Delay
立即返回,所以下一条消息将在没有任何阻止的情况下发送。
public async Task<ResponseMessage> SendMessageAsync(RequestMessage message)
{
int sleepTime;
if (throttler.ShouldThrottle(out sleepTime))
{
await Task.Delay(sleepTime);
}
return await InternalMessageWithoutWaitingAsync(message);
}
我可以将await Task.Delay(sleepTime)
更改为Thread.Sleep(sleepTime)
,然后等待异步,但我想知道在使用任务时这是否是一个好习惯。
答案 0 :(得分:2)
在Thread.Sleep
代码中使用async
不是一个好习惯。
你可能会得到你需要的东西:
private SemaphoreSlim _semaphore = new SemaphoreSlim(N);
public async Task<ResponseMessage> SendMessageAsync(RequestMessage message)
{
await _semaphore.WaitAsync();
try
{
return await InternalMessageWithoutWaitingAsync(message);
}
finally
{
ReleaseSemaphoreAfterDelayAsync();
}
}
private async Task ReleaseSemaphoreAfterDelayAsync()
{
await Task.Delay(TimeInterval);
_semaphore.Release();
}