限制事件处理程序

时间:2015-01-19 03:18:19

标签: c# wpf throttling

在我的WPF应用程序中,我有一个在我的UI元素的MouseEnter事件上调用的事件处理程序:

myUiElement.MouseEnter += myEventHandler

我想限制myEventHandler,所以它不会每秒被调用一次以上。我怎样才能做到这一点? Rx是最好的方法吗?如果它有所作为,我使用的是.NET 4.0。

另外,我需要确保在下一个MouseEnter事件之前始终调用MouseLeave事件;我需要自己管理吗?或者框架是否已经设计好,以便在下一个MouseEnter事件之前始终调用MouseLeave事件?如果我在这些事件处理程序中有异步代码怎么办?

3 个答案:

答案 0 :(得分:7)

您可以使用反应式扩展,但您可以使用计时器轻松完成此操作。

设置一个标志和一个Timer。当计时器tick事件触发时,将标志设置为false,禁用计时器,并运行事件的代码。然后,在控件事件处理程序中,如果设置了标志,则跳过处理程序代码。

bool flag;
DispatcherTimer timer;

public constructor()
{
    timer = new DispatcherTimer();
    timer.Interval = TimeSpan.FromSeconds(1);
    timer.Tick += (s,e) => {
        flag = false;
        timer.Stop()
        DoThrottledEvent();
    }
}

void mouse_enter(object sender, MouseEventArgs args)
{
    if(!flag)
    {
        flag = true;
        timer.Start();
    }
}

void DoThrottledEvent()
{
    //code for event here
}

反应式扩展引入了额外的依赖性,但它们有点乐趣。如果你有兴趣,那就去吧!

答案 1 :(得分:6)

使用Rx,您想使用the Sample method或Throttle。

这样的事情应该有效(未经测试):

Observable
  .FromEventPattern<TextChangedEventArgs>(myUiElement, "MouseEnter");
  .Sample(TimeSpan.FromSeconds(1));
  .Subscribe(x=>...Do Stuff Here...);

Sample和Throttle之间的区别在于,无论何时采用最后一个值,Sample都将每1秒获取一个值,而Throttle将获取一个值,然后等待另一个1秒再取出另一个值。

这可能取决于你拍摄的内容......

答案 2 :(得分:3)

另一种方法是使用私有字段来跟踪上次鼠标事件发生时的“时间”,并且只在该时间超过一秒之前继续处理。

DateTime _lastMouseEventTime = DateTime.UtcNow;

void OnMouseEnter(object sender, MouseEventArgs e)
{
    DateTime now = DateTime.UtcNow;
    if (now.Subtract(_lastMouseEventTime).TotalSeconds >= 1)
    {
        // do stuff...
    }
    _lastMouseEventTime = now;
}

这确保“东西”至少间隔一秒完成,这就是我认为你要求的东西。

相关问题