title: How to limit number of async IO tasks to database?
body: <p>I have a list of <code>id's</code> and I want to get data for each of those <code>id</code> in parallel from database. My below <code>ExecuteAsync</code> method is called at very high throughput and for each request we have around <code>500 ids</code> for which I need to extract data.</p>
  
  <p>So I have got below code where I am looping around list of <code>ids</code> and making async calls for each of those <code>id</code> in parallel and it works fine.</p>
  
  <pre><code>private async Task&lt;List&lt;T&gt;&gt; ExecuteAsync&lt;T&gt;(IList&lt;int&gt; ids, IPollyPolicy policy,
      Func&lt;CancellationToken, int, Task&lt;T&gt;&gt; mapper) where T : class
  {
      var tasks = new List&lt;Task&lt;T&gt;&gt;(ids.Count);
      // invoking multiple id in parallel to get data for each id from database
      for (int i = 0; i &lt; ids.Count; i++)
      {
          tasks.Add(Execute(policy, ct =&gt; mapper(ct, ids[i])));
      }
  
      // wait for all id response to come back
      var responses = await Task.WhenAll(tasks);
  
      var excludeNull = new List&lt;T&gt;(ids.Count);
      for (int i = 0; i &lt; responses.Length; i++)
      {
          var response = responses[i];
          if (response != null)
          {
              excludeNull.Add(response);
          }
      }
      return excludeNull;
  }
  
  private async Task&lt;T&gt; Execute&lt;T&gt;(IPollyPolicy policy,
      Func&lt;CancellationToken, Task&lt;T&gt;&gt; requestExecuter) where T : class
  {
      var response = await policy.Policy.ExecuteAndCaptureAsync(
          ct =&gt; requestExecuter(ct), CancellationToken.None);
      if (response.Outcome == OutcomeType.Failure)
      {
          if (response.FinalException != null)
          {
              // log error
              throw response.FinalException;
          }
      }
  
      return response?.Result;
  }
  </code></pre>
  
  <p><strong>Question:</strong></p>
  
  <p>Now as you can see I am looping all <code>ids</code> and making bunch of async calls to database in parallel for each <code>id</code> which can put lot of load on database (depending on how many request is coming). So I want to limit the number of async calls we are making to database. I modified <code>ExecuteAsync</code> to use <code>Semaphore</code> as shown below  but it doesn't look like it does what I want it to do:</p>
  
  <pre><code>private async Task&lt;List&lt;T&gt;&gt; ExecuteAsync&lt;T&gt;(IList&lt;int&gt; ids, IPollyPolicy policy,
      Func&lt;CancellationToken, int, Task&lt;T&gt;&gt; mapper) where T : class
  {
      var throttler = new SemaphoreSlim(250);
      var tasks = new List&lt;Task&lt;T&gt;&gt;(ids.Count);
      // invoking multiple id in parallel to get data for each id from database
      for (int i = 0; i &lt; ids.Count; i++)
      {
          await throttler.WaitAsync().ConfigureAwait(false);
          try
          {
              tasks.Add(Execute(policy, ct =&gt; mapper(ct, ids[i])));
          }
          finally
          {
              throttler.Release();
          }
      }
  
      // wait for all id response to come back
      var responses = await Task.WhenAll(tasks);
  
      // same excludeNull code check here
  
      return excludeNull;
  }
  </code></pre>
  
  <p>Does Semaphore works on <code>Threads</code> or <code>Tasks</code>? Reading it <a href="https://dejanstojanovic.net/aspnet/2018/august/limit-number-of-tasks-running-in-parallel-in-net/" rel="nofollow noreferrer">here</a> looks like Semaphore is for Threads and SemaphoreSlim is for tasks.</p>
  
  <p>Is this correct? If yes then what's the best way to fix this and limit the number of async IO tasks we make to database here.</p>