using (new Throttle()) {
  ... do my expensive operation here ...
}using System;
using System.Collections;
using System.Web;
using System.Web.Caching;
/// <summary>
/// This is used to throttle anything really, it throws an exception if too many are running simultaneously
/// It works by storing the runs in the http cache
/// Use this with a 'using' statement surrounding your work, eg:
/// 
/// using (new Throttle()) {
///   ... work to be throttled ...
/// }
/// </summary>
public class Throttle : IDisposable
{
  // Used to lock all instances of the throttle, so they don't walk over each other when using the http cache
  static object cacheLock = new object();
  // Max simultaneous users
  const int max = 10;
  // The timeout in seconds at which to consider each run to have finished anyway, eg in case the throttle forgets to clear it
  const int timeout = 30;
  // What prefix to give the names in the cache
  const string cacheEntryNamePrefix = "Throttle";
  // The name of the cache entry used by this particular throttled run
  string thisCacheEntryName;
  /// <summary>
  /// Checks that we haven't hit the throttle, and if so it throws an exception
  /// Then it registers the current run in the cache, to be forgotten when finished
  /// </summary>
  public Throttle() {
    lock (cacheLock) {
      // Check we haven't hit the maximum
      int runners = 0;
      foreach (DictionaryEntry kv in HttpContext.Current.Cache)
        if (kv.Key.ToString().StartsWith(cacheEntryNamePrefix))
          runners++;
      if (runners >= max)
        throw new Exception("Too many people accessing the system right now. Please retry soon.");
      // Register this one into the cache
      thisCacheEntryName = cacheEntryNamePrefix + System.Guid.NewGuid().ToString();
      HttpContext.Current.Cache.Add(thisCacheEntryName, 1, null, DateTime.Now.AddSeconds(timeout), Cache.NoSlidingExpiration, CacheItemPriority.Normal, null);
    }
  }
  /// <summary>
  /// Removes the entry from the cache
  /// </summary>
  public void Dispose() {
    lock (cacheLock) {
      HttpContext.Current.Cache.Remove(thisCacheEntryName);
    }
  }
}Thanks for reading! And if you want to get in touch, I'd love to hear from you: chris.hulbert at gmail.

(Comp Sci, Hons - UTS)
Software Developer (Freelancer / Contractor) in Australia.
I have worked at places such as Google, Cochlear, Assembly Payments, News Corp, Fox Sports, NineMSN, FetchTV, Coles, Woolworths, Trust Bank, and Westpac, among others. If you're looking for help developing an iOS app, drop me a line!
Get in touch:
    [email protected]
    github.com/chrishulbert
    linkedin