Effective speed limitation of asynchronous tasks (N executions per time interval)

How to implement an effective algorithm for speed limitation (N executions of a certain action in a period of time) when using .Net 4.0 / 4.5 Tasks? For example, I want SendMessageAsync block (without sending another message) if there are more than N messages sent per second.

  await Task.WhenAll( Enumerable.Range(0, TOTAL_MESSAGES) .Select(async x => { await clientSession.SendMessageAsync(CreateMessage()); })); 

I tried using Task.Delay inside SendMessageAsync , but since waiting for Task.Delay returned immediately, the next message will be sent without any blockage.

 public async Task<ResponseMessage> SendMessageAsync(RequestMessage message) { int sleepTime; if (throttler.ShouldThrottle(out sleepTime)) { await Task.Delay(sleepTime); } return await InternalMessageWithoutWaitingAsync(message); } 

I could change await Task.Delay(sleepTime) to Thread.Sleep(sleepTime) , waiting before moving on to async, but I wonder if this is good practice when using Jobs.

+4
source share
1 answer

Using Thread.Sleep not good practice in async code.

You could get what you need:

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

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


All Articles