-1

In my program, sometimes a function needs to be executed when an event is fired, sometimes not, and there seems to be a problem with this. In order to understand that problem, I would like to know what happens in the following cases:

_manager.InputOkHandler += InputHandler; // add the InputHandler to the event.
...
_manager.InputOkHandler += InputHandler; // add the same InputHandler to the event again. (1)
...
_manager.InputOkHandler -= InputHandler; // remove an/the InputHandler from the event. (2)

... and at another moment:

_manager.InputOkHandler += InputHandler; // add the Input Handler to the event.
...
_manager.InputOkHandler -= InputHandler; // remove the InputHandler from the event.
...
_manager.InputOkHandler -= InputHandler; // remove an InputHandler from the event. (3)
  • (1) : will the InputHandler be added twice? If yes, what does this mean?
  • (2) : will only one InputHandler be removed or both (if possible)?
  • (3) : will this raise an Exception? If yes, which one?

... and finally: is it possible to show a list of all "subscribed" functions/methods to an event and how?

Dominique
  • 16,450
  • 15
  • 56
  • 112
  • For (1) : Yes the handler will be added twice, what it means => It will be executed twice for each time the event was triggered (and there is no guarantee as the execution order). Setting up a simple test for the other points. – Irwene Oct 24 '22 at 14:03
  • "There seems to be a problem with this". What's the problem? – JuanR Oct 24 '22 at 14:07
  • @JuanR: either the delegates is launched when it should not, or just the opposite (the result is quite messy) and I'm trying to reduce the number of things which might go wrong. – Dominique Oct 24 '22 at 14:12
  • Well, I am pretty sure the runtime doesn't just launch events on its own. :-) You are probably experiencing timing/threading issues (the event is called before you have a chance to unsubscribe from it). Based on the little bit of code you shared though, an alternate approach to this would be to always execute the handler but have it check for some condition inside and abort when necessary. – JuanR Oct 24 '22 at 14:32
  • @JuanR: in order to be sure that the event handler is not added twice, I wanted to add a check, but this seems not to be possible: `if (_Manager.Handler == null)` results in compilation error "CS0070" (CS0070 C# The event can only appear on the left hand side of += or -= (except when used from within the type)). How can I avoid adding it twice? – Dominique Oct 25 '22 at 06:19
  • The way eventhandlers get managed in this question seems promising: https://stackoverflow.com/questions/4496799 (I mean, when adding an event handler, remove it first in order to be sure not to add it twice). – Dominique Oct 25 '22 at 06:38

2 Answers2

2

Ok, so I've got a snippet to answer all of those:

public class A
{
    public event EventHandler MyEvent;

    public void RaiseEvent()
    {
        MyEvent?.Invoke(null, EventArgs.Empty);
    }

    public Delegate[] GetInvocationList()
    {
        return MyEvent.GetInvocationList();
    }
}

public void del1(object sender, EventArgs args)
{
    Console.WriteLine("1");
}

public void del2(object sender, EventArgs args)
{
    Console.WriteLine("2");
}

var a = new A();

a.MyEvent += del1;
a.MyEvent += del1;
a.MyEvent += del2;

a.RaiseEvent();
/*
Outputs: 
1
1
2
*/

a.MyEvent -= del1;

a.RaiseEvent();
/*
Outputs:
1
2
*/

a.MyEvent -= del2;
a.MyEvent -= del2;

a.RaiseEvent();
/*
Outputs:
1
*/

Console.WriteLine($"{a.GetInvocationList().Length} subscriptions left")
/*
Outputs: 
1 subscriptions left
*/

So to answer all your points in order:

  1. Yes, the handler will be added twice, which means it will be called twice when the event is raised
  2. Only one handler will be removed
  3. No, no exceptions will be thrown if you try to remove a handler which is not present in the subscriptions
  4. You can access the collection of subscriptions, but as an array of delegates and only in the class where the event was declared.
Irwene
  • 2,807
  • 23
  • 48
1

will the InputHandler be added twice? If yes, what does this mean?

Yes, and it means that the handler will be invoked twice whenever the event is raised.

will only one InputHandler be removed or both (if possible)?

Only one

will this raise an Exception? If yes, which one?

No.

You should be careful to only add event handlers once, and deterministically remove it. A typical case would be to add the event handler in the constructor, and remove it in the dispose method. In some cases it might make sense to use a helper method for registration that returns a IDiposable, so you can write using(MyEvent.Register(MyEventHandler)){....}.

JonasH
  • 28,608
  • 2
  • 10
  • 23
  • I can confirm that your answer is correct. My application's `InputOKHandler` seems to have an `_invocationCount`, which gets increased, every time I do an `+=`. And indeed, once the `InputOkHandler` becomes `null` and I remove one (`-=`), there is no exception. – Dominique Oct 24 '22 at 14:45