TL; DR:我是否可以使附加到许多事件的处理程序只触发一次,即使我知道所有事件都会被触发?
我试图收听一组对象,每个对象都会完成一项特定任务,然后通知所有者它已完成。为此,我只是循环遍历集合并为每个对象添加了一个事件处理程序
foreach(var obj in collection)
{
obj.Event += GroupHandler;
}
并且工作正常。但是,因为我知道任务将在大约相同的时间内完成,并且因为如果我提前排队一点并不重要,我希望有办法确保一旦GroupHandler被提升,它就会赢得&# 39;对于当前的执行集再次提出,所以我可以做类似的事情:
private void GroupHandler(object sender, EventArgs e)
{
foreach(var obj in collection)
{
obj.QueueNext();
}
}
理想情况下,我最终会得到像
这样的东西private void GroupHandler(object sender, EventArgs e)
{
if(GroupHandler.HasRun) return;
foreach(var obj in collection)
{
obj.QueueNext();
}
}
我知道我可以使用一些全局bool(或者更可能使用int来跟踪周期)但我并不喜欢这样的解决方案。我正在寻找比这更好的东西。
答案 0 :(得分:0)
正如古斯曼在评论中所说,你可以只有一个对象触发事件。这样你知道它每个事件集只执行一次。
或者,您可以设置计时器,计数器和标志。在第一个事件执行时设置标志,然后启动计时器。只要设置了标志,就忽略其余的事件。将计数器设置为您跟踪的对象数量,并在每个计数器触发其事件时递减计数器。当计时器到期或计数器达到零时,重置标志,重置计数器并取消计时器。这可能会很快变得复杂,并且可能会有一堆极端情况,所以如果你不太关心时间,那么第一种方法要好得多。尽可能简化。
答案 1 :(得分:0)
我最终使用Gusman在评论中提到的删除了事件处理程序。真正的关键是找出重新连接它们的位置。所以我最终在QueueNext调用中传递了处理函数。
代码看起来像这样
private void GroupHandler(object sender, EventArgs e)
{
foreach(var obj in collection)
{
obj.Event -= GroupHandler;
}
foreach(var obj in collection)
{
obj.QueueNext(GroupHandler);
}
}
和QueueNext看起来像
public void QueueNext(EventHandler nextHandler)
{
this.Event += nextHandler
QueueNext();
}
这样,事件只被调用一次,并且将为每组执行调用。