异步任务的有效速率限制(每个时间间隔N次执行)

时间:2013-09-01 11:49:23

标签: c# asynchronous async-await c#-5.0

使用.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),然后等待异步,但我想知道在使用任务时这是否是一个好习惯。

1 个答案:

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