C# 处理大量事件处理程序
我有一个可以引发事件的控件C# 处理大量事件处理程序,c#,events,windows-store-apps,C#,Events,Windows Store Apps,我有一个可以引发事件的控件 public event EventHandler ValueUpdated; 我订阅了这个活动 classInstance.ValueUpdated += handler; ... public void handler(...) { oneObject.DoSmthg(...) } 现在的问题是,该事件可以在1分钟内引发1次或在一秒钟内引发1000次。这会导致性能低下(oneObject.DoSmthg(…)不是一个很长的任务运行,但在性能方面并不中立
public event EventHandler ValueUpdated;
我订阅了这个活动
classInstance.ValueUpdated += handler;
...
public void handler(...)
{
oneObject.DoSmthg(...)
}
现在的问题是,该事件可以在1分钟内引发1次或在一秒钟内引发1000次。这会导致性能低下(oneObject.DoSmthg(…)
不是一个很长的任务运行,但在性能方面并不中立)
我不在乎中间步骤。例如,如果事件在一秒钟内引发1000次,只需对第一个事件执行处理程序
方法,最后一个事件完全正常,因为这是为了显示
执行某种“如果许多调用只执行最后一个”的最佳方法是什么?在
处理程序中,使用所需的超时启动或重置计时器N
。触发超时后,N
时间内未收到任何事件,因此您可以开始处理
在开始处理之前停止计时器。我认为,还值得一看反应式扩展:
使用微软的反应式框架(NuGet“Rx Main”)很容易处理这种情况
因此,考虑到这一类:
public class Foo
{
public event EventHandler ValueUpdated;
}
我可以编写以下代码,将事件转换为每秒最多触发一次的Rx可观测事件:
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 */
});
通过调用以下命令取消订阅(分离)可观察对象:
subscription.Dispose();
考虑到这是一个控件,您可能只希望在用户完成与该控件的交互后执行该操作。因此,在您的属性更改
事件处理程序中,停止并启动一个调度程序
,当它触发时将启动长时间运行的进程。停止然后再次启动计时器的原因是因为它可以有效地重新启动计时器
这方面的实现可能如下所示(假设长时间运行的进程由ExternalEvent
启动):
说得好。但这并不是一个非常吸引人的解决方案,因为两台计算机的计算时间可能非常不同。除此之外,这并不能确保最后一条被执行:(我不知道你的第一句话是什么意思,我也不认为你的第二句话是真的。你也可以将事件及其接收日期存储在一个列表中,然后让另一个线程处理该列表。你要寻找的术语是“反弹回事件”无论如何。耶!Thx的关键字,正是我要找的:)
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();
}