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