2016-05-03 4 views
0

TL; DR: Могу ли я сделать обработчик, прикрепленный ко многим событиям, только один раз, даже если я знаю, что все события будут уволены?Mulitple Events, Один обработчик называется один раз

Я пытаюсь выслушать коллекцию объектов, каждая из которых выполнит конкретную задачу, а затем уведомит владельца о том, что она завершена. Для этого я просто зациклился на коллекции и добавил обработчик событий для каждого объекта.

foreach(var obj in collection) 
{ 
    obj.Event += GroupHandler; 
} 

и это прекрасно работает. Однако, поскольку я знаю, что задачи будут выполняться примерно в одно и то же время, и поскольку это действительно не имеет значения, если я стану в очереди немного раньше, я бы хотел, чтобы после того, как GroupHandler поднят, он снова не будет поднят для текущего исполнения набора, так что я мог бы сделать что-то вроде:

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 для отслеживания циклов), но мне это не нравится как решение. Я ищу что-то более приятное, чем это.

+1

Отсоедините событие от объектов при первом вызове. – Gusman

+0

Но я хотел бы, чтобы они снова поднялись на более поздний срок. Вероятно, через 15-20 секунд вниз по дороге –

+0

Затем снова подключите их, но я верю, что вы не замечаете проблему, если вам все равно, какой из объектов закончен, а затем просто присоедините к одному из объектов. – Gusman

ответ

0

Я закончил работу с тем, что Гусман упомянул в комментариях, и удалил обработчики событий. Реальный ключ, хотя и выяснял, где их снова подключить. Поэтому я закончил передачу функции обработчика в вызове 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(); 
} 

таким образом событие вызывается только один раз, и будет вызываться для каждого набора исполнения.

0

Как сказал Гусман в комментариях, у вас может быть только один из объектов, сгоревших от события. Таким образом, вы знаете, что он выполняется только один раз для каждого события.

В качестве альтернативы вы можете настроить таймер, счетчик и флаг. Установите флаг при первом запуске события, а затем запустите таймер. Пока флаг установлен, игнорируйте остальные события. Установите счетчик на количество объектов, которые вы отслеживаете, и уменьшите счетчик, поскольку каждый из них отключает свое событие. Когда либо таймер истекает, либо счетчик достигает нуля, сбросьте флаг, сбросьте счетчик и отмените таймер. Это может быстро усложниться и может иметь кучу угловых случаев, поэтому, если вас не волнует слишком много времени, то первый способ намного лучше. Упростите как можно больше.

+0

Вы не ошибаетесь, потому что это сложно, я пробовал что-то похожее на это, и он быстро стал уродливым. Что касается только того, что один из объектов запускает событие, то как я сейчас обхожусь вокруг него, но мне хотелось бы лучше. Проблема только с одним выстрелом заключается в том, что он заставляет предположить, что подключенный объект работает постоянно, что не так сложно реализовать, но это не совсем тот дизайн, который я собираюсь сделать. –

+0

Что определяет границы «набора событий»? Это будет диктовать имеющиеся решения. Если каждый объект срабатывает как минимум один раз, то счетчик может работать лучше всего. Если это ограничено во времени, то придерживайтесь таймера. Здесь огромное количество вариантов. Выберите самый простой и удобный метод. –

Смежные вопросы