我有一个可以引发事件的控件。
public event EventHandler ValueUpdated;
我订阅了这个活动
classInstance.ValueUpdated += handler;
...
public void handler(...)
{
oneObject.DoSmthg(...)
}
现在问题是这个事件可以在1分钟内提升1次,或者在一秒钟内提升1000次。这导致表现不佳(oneObject.DoSmthg(...)
不是长期任务,但在表现方面不是中立的。)
我不关心中间步骤。例如,如果事件在一秒钟内被提升1000次,则只需执行第一个事件上升的handler
方法,最后一个事件完全正常,因为这是出于显示目的。
执行某种“如果多次调用堆栈只执行最后一次”的最佳方法是什么?
答案 0 :(得分:1)
使用Microsoft的Reactive Framework(NuGet" Rx-Main")处理这是一个非常简单的情况。
所以给这个课:
"/usr/lib/php/extensions/no-debug-non-zts-20121212/#INST@17000#:
我可以编写此代码将事件转换为Rx Observable,每秒最多只触发一次:
public class Foo
{
public event EventHandler ValueUpdated;
}
Throttle有这种语义:
忽略可观察序列中的值,这些值在指定的source和dueTime到期之前跟随另一个值。
现在我可以像这样订阅(附加)到observable:
var values =
Observable
.FromEventPattern(h => foo.ValueUpdated += h, h => foo.ValueUpdated -= h)
.Throttle(TimeSpan.FromSeconds(1.0));
通过致电:
取消订阅(分离)观察者var subscription =
values
.Subscribe(ep =>
{
/* handle event here */
});
答案 1 :(得分:1)
考虑到这是一个控件,您可能只想在用户完成与控件的交互后执行操作。因此,在PropertyChanged
事件处理程序中,停止并启动DispatcherTimer
,当它触发时将启动长时间运行的进程。停止然后再次启动计时器的原因是因为它有效地重启了计时器。
此实现可能如下所示(假设长时间运行的进程由ExternalEvent
启动):
public event ChangedEvent ExternalEvent;
private DispatcherTimer _timer;
private ChangedEventArgs _lastChangedArgs;
public MyControl()
{
InitializeComponent();
_timer = new DispatcherTimer();
_timer.Tick += new EventHandler(dispatcherTimer_Tick);
_timer.Interval = new TimeSpan(0,0,0,350);
InternalEventGeneratingControl.ChangedEvent += new ChangedEventHandler(ChangedHandler);
}
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
_timer.Stop();
if (ExternalEvent != null)
ExternalEvent(this, _lastChangedArgs);
}
private void ChangedHandler(object sender, ChangedEventArgs e)
{
_timer.Stop();
_lastChangedArgs = e;
_timer.Start();
}
答案 2 :(得分:0)
在handler
中,启动或重置具有所需超时N
的计时器。触发超时后,N
时间内未收到任何事件,因此您可以开始处理。
在开始处理之前停止计时器。
答案 3 :(得分:0)
我认为看看Reactive Extensions也是值得的:
http://www.introtorx.com/uat/content/v1.0.10621.0/17_SequencesOfCoincidence.html