如何在使用RateGate时更改速率限制?

时间:2013-10-25 02:05:06

标签: c# .net rate-limiting ratelimit rategate

我使用简洁的RateGate class来限制发送给服务器的请求数。

我的代码看起来像这样:

var RateLimit = 35;

using(var RateGate = new RateGate(RateLimit, TimeSpan.FromSeconds(1)))
{
    for(var Run = 1; Run <= 50; Run++)
    {
        for(var Batch = 0; Batch < 200; Batch++)
        {
            // Do some work, then...

            MyClass MyClass;

            if(MyClass.RateLimitHit)
            {
                RateLimit--;
            }

            RateGate.WaitToProceed();
        }
    }
}

if(MyClass.RateLimitHit)内,我需要将速率限制降低1.不仅仅是变量RateLimit,而是在实际RateGate中运行限制。

在RateGate类中,我看到了:

/// <summary>
/// Number of occurrences allowed per unit of time.
/// </summary>
public int Occurrences { get; private set; }

我的问题是:如果我将private set;更改为set;并在RateGate.Occurrences = RateLimit;之后添加RateLimit--;,这会做我想要的吗?

我尝试了,但看起来RateGate继续以35 / s的最高速率执行。

2 个答案:

答案 0 :(得分:2)

我也想这样做,我通过反转时间和出现找到了一个很好的解决方案。 这是什么意思:

我没有将我的问题表达为“我希望每秒出现N次”,而是将其反转为“我希望每1 / N秒出现一次”。这样,我可以轻松地改变时间单位,而不是修改出现次数(总是为1)。我在课堂上添加了这个方法(你也可以推导出来):

private object _updateTimeUnitLock = new object();
private int nextUpdateTime = 0;
public bool UpdateTimeUnit(TimeSpan timeUnit, TimeSpan dontUpdateBefore)
{
    lock (_updateTimeUnitLock)
    {
        if ((nextUpdateTime == 0) || (nextUpdateTime <= Environment.TickCount))
        {
            TimeUnitMilliseconds = (int)timeUnit.TotalMilliseconds;
            nextUpdateTime = Environment.TickCount + (int)dontUpdateBefore.TotalMilliseconds;

            return true;
        }

        return false;
    }
}

我必须是线程安全的,我需要一种方法来防止在某些时期发生变化,所以在你这边你可能想要删除锁和dontUpdateBefore参数,这意味着你可以设置TimeUnitMilliseconds,这个值将在下一个计时器勾选时被拿起。 现在,要调用它,您只需根据所需的出现次数计算所需的新时间。

希望它能满足您的需求。

<磷>氮

答案 1 :(得分:1)

Occurrences值作为最大计数传递给构造函数中的信号量,因此更改属性不会影响该实例的行为。

public RateGate(int occurrences, TimeSpan timeUnit)
{
    // Snipped all the code that doesn't pertain to this question...

    Occurrences = occurrences;

    // Create the semaphore, with the number of occurrences as the maximum count.
    _semaphore = new SemaphoreSlim(Occurrences, Occurrences);
}

看起来Occurrences更像是一个只读属性,可以让你看到传递给构造函数的内容。