我找到了解决办法。
public class EventThrottler
{
private object _lock = new object();
private CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
private Timer _timer;
public EventThrottler(TimeSpan delay)
{
_timer = new Timer();
_timer.Interval = delay.TotalMilliseconds;
_timer.AutoReset = false;
_timer.Elapsed += OnTimerElapsed;
}
public void TriggerEvent()
{
_timer.Stop();
_timer.Start();
}
public async Task AwaitEvent(CancellationToken token)
{
CancellationTokenSource tokenSource;
lock (_lock)
{
if (_cancellationTokenSource == null)
{
_cancellationTokenSource = new CancellationTokenSource();
}
tokenSource = CancellationTokenSource.CreateLinkedTokenSource(token, _cancellationTokenSource.Token);
}
try
{
await Task.Delay(Timeout.Infinite, tokenSource.Token);
}
catch (TaskCanceledException ex)
{
if (token.IsCancellationRequested)
{
throw;
}
}
}
private void OnTimerElapsed(object sender, ElapsedEventArgs e)
{
CancellationTokenSource tokenSource = null;
lock (_lock)
{
if (_cancellationTokenSource != null)
{
tokenSource = _cancellationTokenSource;
_cancellationTokenSource = null;
}
}
if (tokenSource != null)
{
tokenSource.Cancel();
tokenSource.Dispose();
}
}
}