Жаль, что вы застряли в .NET 2.0, потому что Rx extensions имеет метод Throttle
, который достигает этого эффекта довольно элегантно.
К сожалению, Rx требует как минимум .NET3.5 SP1.
О, хорошо!Вы всегда можете использовать System.Threading.Timer
, чтобы сделать это вместо этого.Синхронизация может быть обеспечена путем использования текущего SynchronizationContext
(это то, что делает BackgroundWorker
).
Вот эскиз класса LaggedMethodPair
, чтобы проиллюстрировать этот подход.Класс получает три входа в своем конструкторе: Action
, который будет выполнен по требованию, еще один Action
, который будет служить обратным вызовом, который будет вызван, когда истечет заданный тайм-аут, и, конечно, сам тайм-аут:
public sealed class LaggedMethodPair
{
private SynchronizationContext _context;
private Timer _timer;
private Action _primaryAction;
private Action _laggedCallback;
private int _millisecondsLag;
public LaggedMethodPair(Action primaryAction,
Action laggedCallback,
int millisecondsLag)
{
if (millisecondsLag < 0)
{
throw new ArgumentOutOfRangeException("Lag cannot be negative.");
}
// Do nothing by default.
_primaryAction = primaryAction ?? new Action(() => { });
// Do nothing by default.
_laggedCallback = laggedCallback ?? new Action(() => { });
_millisecondsLag = millisecondsLag;
_timer = new Timer(state => RunTimer());
}
public void Invoke()
{
// Technically there is a race condition here.
// It could be addressed, but in practice it will
// generally not matter as long as Invoke is always
// being called from the same SynchronizationContext.
if (SynchronizationContext.Current == null)
{
SynchronizationContext.SetSynchronizationContext(
new SynchronizationContext()
);
}
_context = SynchronizationContext.Current;
ResetTimer();
_primaryAction();
}
void ResetTimer()
{
_timer.Change(_millisecondsLag, Timeout.Infinite);
}
void RunTimer()
{
_context.Post(state => _laggedCallback(), null);
}
}
Я написал пример приложения Windows Forms, чтобы показать этот класс в действии.Форма содержит элемент LaggedMethodPair
с таймаутом 2000 мс.Его primaryAction
добавляет элемент в список.Его laggedCallback
добавляет выделенный элемент в представление списка.
Вы можете видеть, что код работает должным образом.
![LaggedMethodPair Test Form](https://i.stack.imgur.com/rH7rq.png)