Skip to content

Instantly share code, notes, and snippets.

@wcharczuk
Created August 14, 2011 21:10
Show Gist options
  • Save wcharczuk/1145315 to your computer and use it in GitHub Desktop.
Save wcharczuk/1145315 to your computer and use it in GitHub Desktop.
Rate Limiter written in c#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Threading;
namespace YourNamespaceHere
{
[Serializable()]
public class RateLimiter
{
public RateLimiter(Int32 requests, TimeSpan interval)
{
this.Requests = requests;
this.Interval = interval;
}
public Int32 Requests { get; set; }
public TimeSpan Interval { get; set; }
private ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
private Dictionary<String, Queue<DateTime>> _internalStorage = new Dictionary<String, Queue<DateTime>>();
public Boolean Process(String address)
{
_lock.EnterUpgradeableReadLock();
try
{
if (!_internalStorage.ContainsKey(address))
{
_lock.EnterWriteLock();
try
{
_internalStorage.Add(address, new Queue<DateTime>());
_internalStorage[address].Enqueue(DateTime.Now);
return true;
}
finally
{
_lock.ExitWriteLock();
}
}
else
{
PurgeOldEntries(address);
_lock.EnterWriteLock();
try
{
_internalStorage[address].Enqueue(DateTime.Now);
return _internalStorage[address].Count <= Requests;
}
finally
{
_lock.ExitWriteLock();
}
}
}
finally
{
_lock.ExitUpgradeableReadLock();
}
}
private void PurgeOldEntries(String address)
{
_lock.EnterWriteLock();
try
{
while (_internalStorage[address].Count > 0 && (DateTime.Now - _internalStorage[address].Peek() > Interval))
{
_internalStorage[address].Dequeue();
}
}
finally
{
_lock.ExitWriteLock();
}
}
}
}
@dasjestyr
Copy link

Is there an example on how to use this? The following doesn't seem to work and the queue appears to just continue piling up.

static void Main()
{
    var limiter = new RateLimiter(10, TimeSpan.FromSeconds(5));

    var t = Task.Run(() =>
    {
        for (var i = 0; i < 100; i++)
        {
            while (!limiter.Process("foo"))
            {
                Task.Delay(1).Wait();
            }

            Console.WriteLine(i);
        }
    });

    Task.WaitAll(t);
    Console.ReadKey();
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment