前言
假如我们有一个上线用户的界面,每个用户上线的时候都会做一定的业务处理和页面刷新。
这样如果在短时间内用户大量进入就会导致页面处理不过来,而产生未响应甚至闪退。
这就要用到防抖和节流了。
它们都用在事件频繁触发并且允许丢失的场景下。
防抖和节流都是为了防止事件频发触发的一种方式。
函数防抖(debounce)
当持续触发某事件时,一定时间间隔内没有再触发事件时,事件处理函数才会执行一次,如果设定的时间间隔到来之前,又一次触发了事件,就重新开始延时。 可以保证最后的事件一定触发,但是可能中间可能新事件一直有,则一直取消触发。
函数节流(throttle)
当持续触发事件时,有规律的每隔一个时间间隔执行一次事件处理函数。 可以保证事件流中稳定的触发事件,但是不能保证最后的事件一定被触发。
函数防抖(debounce)
针对用户上线的场景适用防抖更加合适。
在 C# 页面渲染中,防抖处理通常用于限制用户频繁触发某个操作(如按钮点击、输入框输入等)时的请求或处理次数,以提高系统性能和用户体验。
不带参数
页面内的渲染方法基本上都不是静态的,并且参数可以使用页面的私有参数,方法本身不用传参数。
页面中
代码语言:javascript复制private readonly Action _renderPage;
public AttendanceWindow()
{
//页面初始化时初始化防抖对象
_renderPage = new ZDebounceUtil().Create(RenderUserList, TimeSpan.FromSeconds(0.5));
}
private void RenderUserList()
{
Dispatcher.Invoke(
() =>
{
//UI渲染
}
);
}
//频繁触发的方法
public void UserListChange()
{
//原来调用RenderUserList()改成如下
_renderPage?.Invoke();
}
工具类
ZDebounceUtil.cs
代码语言:javascript复制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;
}
}
带参数示例
下面是一个示例代码,
代码语言:javascript复制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}");
}
// 防抖处理后,只会执行最后一次调用
// 输出:Page 10
}
static void RenderUserList(string pageName)
{
Console.WriteLine($"Rendering {pageName}...");
// 实际的页面渲染逻辑
}
防抖工具类
代码语言:javascript复制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)
不带参数
页面中
代码语言:javascript复制private readonly Action _renderPage;
public AttendanceWindow()
{
//页面初始化时初始化节流对象
_renderPage = new ZThrottleUtil().Create(RenderUserList, TimeSpan.FromSeconds(0.5));
}
private void RenderUserList()
{
Dispatcher.Invoke(
() =>
{
//UI渲染
}
);
}
//频繁触发的方法
public void UserListChange()
{
//原来调用RenderUserList()改成如下
_renderPage.Invoke();
}
工具类
ZThrottleUtil.cs
代码语言:javascript复制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;
}
}