title: Throttling HttpClient requests by some variable
body: <p>I'm writing a class that uses HttpClient to access an API and I want to throttle the number of concurrent calls that can be made to a certain function in this class. The trick is though that the limit is per tenant and multiple tenants might be using their own instance of the class at a time.</p>
  
  <p>My Tenant class is just a container for read-only context information.</p>
  
  <pre><code>public class Tenant
  {
      public string Name { get; }
      public string ApiKey { get; }
  }
  </code></pre>
  
  <p>Here's the ApiClient:</p>
  
  <pre><code>public class ApiClient
  {
      private readonly Tenant tenant;
  
      public ApiClient(Tenant tenant)
      {
          this.tenant = tenant;
      }
  
      public async Task&lt;string&gt; DoSomething()
      {
          var response = await this.SendCoreAsync();
          return response.ToString();
      }
  
      private Task&lt;XElement&gt; SendCore()
      {
          using (var httpClient = new HttpClient())
          {
              var httpRequest = this.BuildHttpRequest();
              var httpResponse = await httpClient.SendAsync(httpRequest);
              return XElement.Parse(await httpResponse.Content.ReadAsStringAsync());
          }
      }
  }
  </code></pre>
  
  <p>What I want to do is throttle the <code>SendCore</code> method and limit it to two concurrent requests <strong>per tenant</strong>. I've read suggestions of using <code>TPL</code> or <code>SemaphoreSlim</code> to do basic throttling (such as here: <a href="https://stackoverflow.com/questions/22492383/throttling-asynchronous-tasks">Throttling asynchronous tasks</a>), but I'm not clear on how to add in the further complication of the tenant.</p>
  
  <p>Thanks for the suggestions.</p>
  
  <p><strong>UPDATE</strong></p>
  
  <p>I've attempted to use a set of <code>SemaphoreSlim</code> objects (one per tenant) contained in a <code>ConcurrentDictionary</code>. This seems to work, but I'm not sure if this is ideal. The new code is:</p>
  
  <pre><code>public class ApiClient
  {
      private static readonly ConcurrentDictionary&lt;string, SemaphoreSlim&gt; Semaphores = new ConcurrentDictionary&lt;string, SemaphoreSlim&gt;();
      private readonly Tenant tenant;
      private readonly SemaphoreSlim semaphore;
  
      public ApiClient(Tenant tenant)
      {
          this.tenant = tenant;
          this.semaphore = Semaphores.GetOrAdd(this.tenant.Name, k =&gt; new SemaphoreSlim(2));
      }
  
      public async Task&lt;string&gt; DoSomething()
      {
          var response = await this.SendCoreAsync);
          return response.ToString();
      }
  
      private Task&lt;XElement&gt; SendCore()
      {
          await this.semaphore.WaitAsync();
          try
          {
              using (var httpClient = new HttpClient())
              {
                  var httpRequest = this.BuildHttpRequest();
                  var httpResponse = await httpClient.SendAsync(httpRequest);
                  return XElement.Parse(await httpResponse.Content.ReadAsStringAsync());
              }
          }
          finally
          {
              this.semaphore.Release();
          }
      }
  }
  </code></pre>