开发者

Problem with event "chaining"

Note: I edited this question to make it easier for other people with the same problem to get help here. To see the original question that fits better with some of the answers, check the edit history.

In a project I ha开发者_开发问答ve a ExecutionManager class that can contain multiple ExecutionSlot's instances. The ExecutionSlot class have several public event fields like this:

public event EventHandlers.ObjectEventHandler<IPlugin> ExecuteCompleted;

For each of these events there is a matching event on ExecutionManager. The desired behavior is that every time on of the ExecutionSlot's raises an event, the matching event is also raised on the containing ExecutionManager.

The implmented solution was that whenever an ExecutionSlot was added to an ExecutionManager the ExectionManager would add its own events to the ExecutionSlot's like this:

executionSlot.ExecuteCompleted += ExecuteCompleted;

There is no need yet to remove an ExecutionSlot, so the events are never removed either.

The problem is that the event on ExecutionManager is not being raised. After confirming that an event was being reaised by an ExecutionSlot I found out that changing the above line to the following fixed the problem:

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

And I could not figure out why, so my question was, what the difference was.

The reason for this difference was that the first adds the current listeners of the ExecutionManager's event to the ExecutionSlot's event. So any listeners added later will not be called when the event is raised. In contrast the latter solution uses a lambda to raise the ExecutionManager's event, which means that the listeners at the time of the event will be called.

The underlying reason for the first solution to fail, is that delegates are immutable. So when you add a new delegate to and event, you are actually creating a new delegate that contains the existing delegates and the added. So any reference to the delegates made before will not contain the newly added delegate.


One idea... perhaps there is somewhere in your code where you are doing:

executionSlot.ExecuteCompleted -= ExecuteCompleted;

which would unsubscribe the event if you use your original subscription syntax, but would not remove it once you made your change.


EDIT: This answer was assuming that ExecuteCompleted was a method. As it's actually a field, that changes things completely. I'll leave this answer here for the sake of posterity.

The first version adds an event handler with a delegate created from an autogenerated method which in turn just calls ExecuteCompleted. It's a bit like this:

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

The second version adds an event handler with a delegate created directly from the ExecuteCompleted method.

Basically the first form is one extra level of redirection. This wouldn't usually make any difference, except for unsubscription as JoelFan mentioned. I would guess that's the problem.

The class raising the event could reflect over the attached handlers and look at the method names, reacting differently in this particular case - but it's very unlikely.


look at this other post on stackoverflow

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

is not the same as

b += a;

It appends the current contents of a to b, so if later more handlers enlist with a, this will not cause them to be called when b is fired


I believe what is happening here is that some sort of temporary object is being created in the first example with an empty event handler that is being called, but does nothing.

The second example, which you say works, is an event handler on your object with the real code. Not entirely sure what's going on there though, but that's my best guess.

Certainly the first example smells bad anyway, since it uses lambda expressions to obfuscate the meaning with no real added value.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜