仅在 C#/WPF 中的给定时间内未触发事件时才执行事件 [重复]
Posted
技术标签:
【中文标题】仅在 C#/WPF 中的给定时间内未触发事件时才执行事件 [重复]【英文标题】:Execute an event only if it wasn't fired for a given amount of time in C#/WPF [duplicate] 【发布时间】:2021-05-03 17:31:20 【问题描述】:我有一个带有 MouseWheel 事件的 WPF 应用程序。本次活动的操作相当繁重。因此,我只想在用户停止滚动时执行此事件(即:如果他在给定的时间内没有滚动)。
在 JS 中,这很容易,我可以将 setTimout
放在一个 var 中,然后如果在执行 setTimeout
之前发生另一个滚动,则在该 var 上执行 clearTimeout
(这对于例如自动完成)。
如何在c#
中实现这一点?
【问题讨论】:
在事件发生时停止并重新启动 DispatcherTimer。在计时器的 Tick 处理程序上执行最终事件操作。 为此使用的搜索词是“去抖动”。例如,weblog.west-wind.com/posts/2017/jul/02/… 或 docs.microsoft.com/en-us/dotnet/api/… 你为什么用“多线程”标签标记问题?您想在与 UI 线程不同的线程上执行繁重的操作吗? @Clemens,太好了,谢谢,您可以添加您的评论作为回复,以便我接受吗? @TheodorZoulias,不,只是因为与计时器相关的操作通常绑定到一个新线程... 【参考方案1】:这很容易使用 Microsoft 的响应式框架(又名 Rx) - NuGet System.Reactive.Windows.Threading
(用于 WPF)并添加 using System.Reactive.Linq;
- 然后你可以这样做:
IObservable<EventPattern<MouseWheelEventArgs>> query =
Observable
.FromEventPattern<MouseWheelEventHandler, MouseWheelEventArgs>(
h => ui.MouseWheel += h, h => ui.MouseWheel -= h)
.Throttle(TimeSpan.FromMilliseconds(250.0))
.ObserveOnDispatcher();
IDisposable subscription =
query
.Subscribe(x =>
/* run expensive code */
);
文档对Throttle
这么说:
忽略来自可观察序列的值,这些值在指定源和到期时间的到期时间之前后跟另一个值。
【讨论】:
【参考方案2】:以下内容可能适合您的需求
public class perRxTickBuffer<T>
private readonly Subject<T> _innerSubject = new Subject<T>();
public perRxTickBuffer(TimeSpan? interval = null)
if (interval == null)
interval = TimeSpan.FromSeconds(1);
Output = _innerSubject.Sample(interval.Value);
public void Tick(T item)
_innerSubject.OnNext(item);
public IObservable<T> Output get;
创建一个实例,其中 T 是您的事件的事件参数类型。
为您的情况设置一个适当的时间跨度值 - 可能是 1/4 秒。
只需从您的事件处理程序中调用Tick()
,然后订阅Output
observable 即可获得受监管的“事件”流。
【讨论】:
这不需要给System.Reactive包添加依赖吗? 我不明白...我应该把没有更多滚动时应该执行的代码放在哪里?以上是关于仅在 C#/WPF 中的给定时间内未触发事件时才执行事件 [重复]的主要内容,如果未能解决你的问题,请参考以下文章
Flutter BLoC mapEventToState 仅在事件的第一次调用时才被调用,并且不会在下次触发该事件时调用
WPF,`Loaded` 事件仅在第一次视图模型初始化时触发,但不会在后续视图模型初始化时触发