多事件,一个叫做一次的处理程序

时间:2016-05-03 20:21:28

标签: c# events eventhandler

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来跟踪周期)但我并不喜欢这样的解决方案。我正在寻找比这更好的东西。

2 个答案:

答案 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();
}

这样,事件只被调用一次,并且将为每组执行调用。