【问题标题】:Use RX to reduce the frequency of mouse move events使用 RX 降低鼠标移动事件的频率
【发布时间】:2013-01-31 19:05:54
【问题描述】:

我是 RX 的新手,但我觉得它应该能够为我希望解决的任务提供一个很好的解决方案。经过相当多的搜索,我仍然没有找到解决方案。

我有一个 WPF 应用程序,其中一个控件执行一些工作以响应某些鼠标移动事件。我想降低事件的频率,以便处理程序的调用频率低于当前情况(因为用户在控件上移动鼠标)。理想情况下,我想要的是设置并订阅一个观察者。观察者应该观察鼠标移动事件,并在特定时间窗口过去后使用最近的事件和参数调用客户端代码,比如 0.2 秒。作为 RX 新手,我首先将我原来的标准事件连接替换为观察者,如下所示:

var mouseMove = Observable.FromEventPattern<MouseEventArgs>(myControl, "MouseMove");

mouseMove.Subscribe(args => myControl_MouseMove(args.Sender, args.EventArgs)); 

这似乎工作正常。

然后我尝试修改观察者以获得我上面描述的行为。我尝试使用 Throttle() 调用和 Sample() 调用。这些并没有产生我预期(或渴望)的结果。事实上,在某些情况下,使用 Throttle/TimeSpan 调用的特定重载会导致我的应用程序死机,我仍然不明白。

这是我尝试过的一个例子:

var mouseMove = Observable.FromEventPattern<MouseEventArgs>(myControl, "MouseMove").Throttle(TimeSpan.FromSeconds(0.2));

mouseMove.Subscribe(args => myControl_MouseMove(args.Sender, args.EventArgs)); 

从阅读开始,Throttle 似乎会吞下事件,直到频率降至特定阈值以下(与我的预期不太一样),而我相信 Sample 会定期对观察到的事件进行采样?我希望在给定的时间间隔内为客户端代码提供最新的事件。如果在该时间间隔内没有记录任何事件,则不应调用客户端。

希望有人可以在这方面帮助 RX 新手。

哦,我还想在控件的生命周期内随时了解(降低频率的)鼠标移动。

最大

【问题讨论】:

    标签: wpf events mouse system.reactive


    【解决方案1】:

    我认为您与 Sample 走在正确的轨道上 - 具体来说,这对您没有什么作用?

    示例 LINQPad sn-p:

    void Main()
    {
        var window = new Window();
        window.Content = ctrl;
        window.Show();
        var mouseMove = Observable
            .FromEventPattern<MouseEventArgs>(window, "MouseMove")
            .Sample(TimeSpan.FromSeconds(0.2));
        var disp = mouseMove.Subscribe(args => myControl_MouseMove(args.Sender, args.EventArgs));     
        window.Closed += (o,e) => disp.Dispose();
    }
    
    ItemsControl ctrl = new ItemsControl();
    
    // Define other methods and classes here
    private void myControl_MouseMove(object sender, MouseEventArgs args)
    {
        ctrl.Dispatcher.BeginInvoke((Action)(() => {ctrl.Items.Add(args.GetPosition(ctrl));}));
    }
    

    【讨论】:

    • 它有点工作,但我现在经常看到杀死我的应用程序的异常:System.Reactive.Core.dll 中发生了“System.InvalidOperationException”类型的第一次机会异常
    • 崩溃发生在鼠标按下事件处理程序中。只有当我在鼠标移动时使用 Sample 调用时才会发生这种情况。
    • 啊,好像是线程问题。我需要做 BeginInvoke
    • @MaxPalmer 或者,您可以使用 ObserveOnDispatcher 并删除 BeginInvoke 调用:var disp = mouseMove.ObserveOnDispatcher().Subscribe(args =&gt; myControl_MouseMove(args.Sender, args.EventArgs));
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-22
    • 2021-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多