概念
函数防抖
(debounce):当频繁持续触发事件时,如果在设定时间间隔内重复触发事件,每次触发时间就重新开始计时,直至指定时间间隔内没有再触发事件,事件处理函数才会执行一次
。函数节流
(throttle):当频繁持续触发事件时,保证每隔指定时间调用一次事件处理函数,指定间隔内只会调用一次
。debounce限制多长时间才能执行一次,
- throttle限制多长时间必须执行一次,
- 一个限制上限、一个限制下限
函数防抖
using System;
using System.ComponentModel;
using System.Threading;
namespace Common
{
/// <summary>
/// 防抖活动--多次重复调用时,间隔固定时长不调用时执行一次
/// </summary>
public class DebounceAction
{
private Timer _timer;
private ISynchronizeInvoke _invoker;
private Action _action;
public TimeSpan Delay { get; private set; }
public DebounceAction(TimeSpan delay)
{
Delay = delay;
}
public DebounceAction(Action action, TimeSpan delay) : this(delay)
{
_action = action;
}
/// <summary>
/// 间隔固定时长不调用时执行一次
/// </summary>
public void Execute(ISynchronizeInvoke invoker = null)
{
Monitor.Enter(this);
bool needExit = true;
try
{
_invoker = invoker;
Cancel();
_timer = new Timer(OnTimeTicked, null, (int)Delay.TotalMilliseconds, Timeout.Infinite);
Monitor.Exit(this);
needExit = false;
}
finally
{
if (needExit)
Monitor.Exit(this);
}
}
/// <summary>
/// 取消防抖操作
/// </summary>
public void Cancel()
{
if (_timer != null)
{
_timer.Dispose();
_timer = null;
}
}
private void OnTimeTicked(object state)
{
Cancel();
if (_action != null)
{
if (_invoker != null && _invoker.InvokeRequired)
{
_invoker.Invoke(_action, null);
}
else
{
_action.Invoke();
}
}
}
}
}
函数节流
using System;
using System.ComponentModel;
using System.Threading;
namespace Common
{
/// <summary>
/// 节流活动--多次重复调用时,每间隔固定时长执行一次
/// </summary>
public class ThrottleAction
{
private Timer _timer;
private Action _action;
private ISynchronizeInvoke _invoker;
public TimeSpan Delay { get; private set; }
public ThrottleAction(TimeSpan delay)
{
Delay = delay;
}
public ThrottleAction(Action action, TimeSpan delay)
: this(delay)
{
_action = action;
}
/// <summary>
/// 每间隔固定时长执行一次
/// </summary>
/// <param name="invoker"></param>
public void Execute(ISynchronizeInvoke invoker = null)
{
Monitor.Enter(this);
bool needExit = true;
try
{
_invoker = invoker;
if (_timer == null)
{
_timer = new Timer(OnTimeTicked, null, (int)Delay.TotalMilliseconds, Timeout.Infinite);
Monitor.Exit(this);
needExit = false;
}
}
finally
{
if (needExit)
Monitor.Exit(this);
}
}
/// <summary>
/// 取消节流操作
/// </summary>
public void Cancel()
{
if (_timer != null)
{
_timer.Dispose();
_timer = null;
}
}
private void OnTimeTicked(object state)
{
Cancel();
if (_action != null)
{
if (_invoker != null && _invoker.InvokeRequired)
{
_invoker.Invoke(_action, null);
}
else
{
_action.Invoke();
}
}
}
}
}