Проблема с событием “объединение в цепочку”

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

В проекте у меня есть класс ExecutionManager, который может содержать экземпляры нескольких ExecutionSlot. Класс ExecutionSlot имеет несколько полей общественного мероприятия как это:

public event EventHandlers.ObjectEventHandler<IPlugin> ExecuteCompleted;

Для каждого из этих событий на ExecutionManager существует событие соответствия. Желаемое поведение состоит в том, что каждый раз на повышений ExecutionSlot событие, событие соответствия также генерируется на содержании ExecutionManager.

implmented решение состояло в том, что каждый раз, когда ExecutionSlot был добавлен к ExecutionManager, ExectionManager добавит свои собственные события к ExecutionSlot как это:

executionSlot.ExecuteCompleted += ExecuteCompleted;

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

Проблема состоит в том, что событие на ExecutionManager не генерируется. После подтверждения, что событие было reaised ExecutionSlot, я узнал, что изменение вышеупомянутой строки к следующему решило проблему:

executionSlot.ExecuteCompleted += (sender, eventArgs) => ExecuteCompleted(sender, eventArgs);

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

Причина этого различия состояла в том, что первое добавляет текущих слушателей события ExecutionManager к событию ExecutionSlot. Таким образом, любые слушатели добавили, позже не будет назван, когда событие генерируется. По контрасту последнее решение использует лямбду, чтобы сгенерировать событие ExecutionManager, что означает, что слушателей во время события позвонят.

Базовая причина первого решения перестать работать, то, что делегаты неизменны. Таким образом, когда Вы добавляете нового делегата в и событие, Вы на самом деле создаете нового делегата, который содержит существующих делегатов и добавленное. Таким образом, любая ссылка на делегатов сделала, прежде не будет содержать недавно добавленного делегата.

6
задан Jacob Poul Richardt 2 February 2010 в 12:39
поделиться

4 ответа

взгляните на этот другой пост на stackoverflow

b += (s, e) => a(s, e);

не тот же самый, что

b += a;

Он добавляет текущее содержимое a к b, так что если позже больше обработчиков запишут a, это не вызовет их, когда b будет выстрелен

3
ответ дан 9 December 2019 в 22:35
поделиться

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

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

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

.
0
ответ дан 9 December 2019 в 22:35
поделиться

Одна идея... возможно, где-то в вашем коде есть:

executionSlot.ExecuteCompleted -= ExecuteCompleted;

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

4
ответ дан 9 December 2019 в 22:35
поделиться

РЕДАКТИРОВАТЬ: этот ответ предполагал, что ExecuteCompleted был методом . Поскольку на самом деле это поле , оно полностью меняет ситуацию. Я оставлю этот ответ здесь для потомков.

Первая версия добавляет обработчик событий с делегатом, созданным из автоматически сгенерированного метода, который, в свою очередь, просто вызывает ExecuteCompleted . Это примерно так:

private void <>AutogeneratedMethodWithUnspeakableName(object sender, EventArgs e)
{
    ExecuteCompleted(e);
}
...
executionSlot.ExecuteCompleted += <>AutogeneratedMethodWithUnspeakableName;

Вторая версия добавляет обработчик событий с делегатом, созданным непосредственно из метода ExecuteCompleted .

По сути, первая форма - это один дополнительный уровень перенаправления. Обычно это не имеет никакого значения, за исключением отказа от подписки, как упоминал Джоэл Фан. Я бы предположил , что проблема.

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

4
ответ дан 9 December 2019 в 22:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: