前言
假如我们有一个上线用户的界面,每个用户上线的时候都会做一定的业务处理和页面刷新。
这样如果在短时间内用户大量进入就会导致页面处理不过来,而产生未响应甚至闪退。
这就要用到防抖和节流了。
它们都用在事件频繁触发并且允许丢失的场景下。
防抖和节流都是为了防止事件频发触发的一种方式。
函数防抖(debounce)
当持续触发某事件时,一定时间间隔内没有再触发事件时,事件处理函数才会执行一次,如果设定的时间间隔到来之前,又一次触发了事件,就重新开始延时。
可以保证最后的事件一定触发,但是可能中间可能新事件一直有,则一直取消触发。
函数节流(throttle)
当持续触发事件时,有规律的每隔一个时间间隔执行一次事件处理函数。
可以保证事件流中稳定的触发事件,但是不能保证最后的事件一定被触发。
函数防抖(debounce)
针对用户上线的场景适用防抖更加合适。
在 C# 页面渲染中,防抖处理通常用于限制用户频繁触发某个操作(如按钮点击、输入框输入等)时的请求或处理次数,以提高系统性能和用户体验。
不带参数
页面内的渲染方法基本上都不是静态的,并且参数可以使用页面的私有参数,方法本身不用传参数。
页面中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| private readonly Action _renderPage; public AttendanceWindow() { _renderPage = new ZDebounceUtil().Create(RenderUserList, TimeSpan.FromSeconds(0.5)); }
private void RenderUserList() { Dispatcher.Invoke( () => { } ); }
public void UserListChange() { _renderPage?.Invoke(); }
|
工具类
ZDebounceUtil.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| using System; using System.Threading;
public class ZDebounceUtil { private Timer _timer; private Action _action; private TimeSpan _timeout;
private void DebouncedAction() { _timer?.Dispose(); _timer = new Timer( state => { _action(); }, null, _timeout, TimeSpan.FromMilliseconds(-1) ); }
public Action Create(Action action, TimeSpan timeout) { _action = action; _timeout = timeout; return DebouncedAction; } }
|
带参数示例
下面是一个示例代码,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| static void Main(string[] args) { Action<string> renderPage = new Debounce<string>().Create(RenderUserList, TimeSpan.FromSeconds(0.5));
for (int i = 1; i <= 10; i++) { renderPage.Invoke($"Page {i}"); }
}
static void RenderUserList(string pageName) { Console.WriteLine($"Rendering {pageName}..."); }
|
防抖工具类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| using System; using System.Threading;
public class Debounce<T> { private Timer _timer; private Action<T> _action;
public Action<T> Create(Action<T> action, TimeSpan timeout) { _action = action; return DebouncedAction; void DebouncedAction(T param) { _timer?.Dispose(); _timer = new Timer( state => { _action(param); }, null, timeout, TimeSpan.FromMilliseconds(-1) ); } } }
|
在此示例中,我们定义了一个名为 Debounce<T> 的通用类。
通过调用 Create 方法,我们可以创建一个经过防抖处理的函数。
当调用 renderPage.Invoke(pageName) 时,会在指定的时间间隔内只执行最后一次调用。
在 Render 方法中,我们模拟了实际的页面渲染逻辑,你可以根据实际情况进行修改。
函数节流(throttle)
不带参数
页面中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| private readonly Action _renderPage; public AttendanceWindow() { _renderPage = new ZThrottleUtil().Create(RenderUserList, TimeSpan.FromSeconds(0.5)); }
private void RenderUserList() { Dispatcher.Invoke( () => { } ); }
public void UserListChange() { _renderPage.Invoke(); }
|
工具类
ZThrottleUtil.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| using System; using System.Threading;
public class ZThrottleUtil { private Timer _timer; private Action _action; private TimeSpan _timeout;
private void ThrottleAction() { if (_timer != null) { return; } _timer = new Timer( state => { _action(); _timer?.Dispose(); _timer = null; }, null, _timeout, TimeSpan.FromMilliseconds(-1) ); }
public Action Create(Action action, TimeSpan timeout) { _action = action; _timeout = timeout; return ThrottleAction; } }
|