【问题标题】:Execute an event only if it wasn't fired for a given amount of time in C#/WPF [duplicate]仅在 C#/WPF 中的给定时间内未触发事件时才执行事件 [重复]
【发布时间】: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,不,只是因为与计时器相关的操作通常绑定到一个新线程...

标签: c# wpf multithreading settimeout


【解决方案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包添加依赖吗?
    • 我不明白...我应该把没有更多滚动时应该执行的代码放在哪里?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-18
    • 1970-01-01
    • 2022-08-14
    • 2022-01-08
    相关资源
    最近更新 更多