2013-10-25 3 views
2

Я использую краткий RateGate class, чтобы ограничить количество запросов, отправляемых на сервер.Как изменить ограничение скорости при использовании RateGate?

Мой код выглядит примерно так:

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; к и добавить RateGate.Occurrences = RateLimit; после RateLimit--; будет это делать то, что я хочу?

Я пробовал, но похоже, что RateGate продолжает выполнять с максимальной скоростью 35/с.

+0

Просто для уточнения ... для щедрот вы ищете модифицированный класс RateGate, или новый класс, который наследует и переопределяет/расширяют некоторые функции из класса RateGate? –

ответ

2

Я тоже хотел это сделать, и я нашел хорошее решение, инвертируя время и события. Что означает:

Вместо того, чтобы выражать мою проблему как «Я хочу N вхождения в секунду», я обратил ее как «Я хочу 1 вхождение за 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 param, что означает, что вы можете просто установить TimeUnitMilliseconds, и это значение будет поднято при следующем тике таймера. Теперь, чтобы назвать это, вам просто нужно вычислить новое время, которое вы хотите, в зависимости от количества желаемых событий.

Надеюсь, он может соответствовать вашим потребностям.

Н.

+0

Большое спасибо за ваш ответ Николас, это выглядит многообещающе! Пойдемте, чтобы проверить это в ближайшее время. –

+0

Это прекрасно работает, спасибо за идею обращения вспять проблемы на использование 1 вхождения за (1000/(число в секунду)) миллисекунд. В конце концов, код становится таким же простым, как «RateGate.TimeUnitMilliseconds = 1000/35;' –

+0

Конечно, 'public int TimeUnitMilliseconds {get; частный набор; } 'также должен быть изменен с' private set; 'на' set; ' –

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); 
} 

Похоже вхождения больше только для чтения свойства, которое позволяет вам видеть то, что было передано в конструктор.

+0

Спасибо за объяснение, почему это не работает Джефф; Я не думаю, что у вас есть какие-то идеи о том, как изменить максимальный предел скорости, в то время как внутри исполняемого «RateGate»? –

+0

Я не уверен, возможно ли это с текущей договоренностью. Если я правильно понимаю, этот семафор контролирует поток вещей, поэтому, если вы его уничтожите, он сбросит состояние. При этом может быть возможно написать метод (или реализовать набор), чтобы он использовал текущий счет существующего семафора при создании нового ... что-то вроде: '_semaphore = new SemaphoreSlim (_semaphore.CurrentCount , newOccurrenceValue) ', но я не могу гарантировать его поведение. –

+0

Теперь я добавил щедрость; возможно, вы хотели бы попытаться выяснить, возможно ли это ... –

Смежные вопросы