我很难想象使用async/await
在.NET中事件调节器(又名去抖动器)的外观。
请考虑以下代码。
/// <summary>
/// A local, in-memory event throttler/debuouncer.
/// </summary>
public class EventThrottler
{
private TimeSpan _delay = TimeSpan.FromSeconds(5);
/// <summary>
/// Begin a timer to release callers of "AwaitEvent".
/// If a timer has already begun, push it back for the length of 5 seconds.
/// This method should not block.
/// </summary>
public void TriggerEvent()
{
}
/// <summary>
/// Multiple people can await.
/// Callers will be released exactly 5 seconds after the last call to "TriggerEvent".
/// If no call is ever made to "TriggerEvent", consumers of "AwaitEvent" will wait, indefinitely (or until CancellationToken is triggered).
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
public Task AwaitEvent(CancellationToken token)
{
return Task.CompletedTask;
}
}
我应该在这里使用什么方法?
ManualResetEvent
的所有呼叫者都可以等待的AwaitEvent
吗?然后,System.Timers.Timer
在每次调用TriggerEvent
之后被重置,最终将释放事件吗?
答案 0 :(得分:0)
我找到了解决方法。
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();
}
}
}