Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to ensure an event is only subscribed to once

I would like to ensure that I only subscribe once in a particular class for an event on an instance.

For example I would like to be able to do the following:

if (*not already subscribed*) {     member.Event += new MemeberClass.Delegate(handler); } 

How would I go about implementing such a guard?

like image 235
Glen T Avatar asked Dec 15 '08 05:12

Glen T


People also ask

Can an event have multiple subscribers?

An event can have multiple subscribers. A subscriber can handle multiple events from multiple publishers. Events that have no subscribers are never raised.

Do I need to unsubscribe events c#?

To prevent your event handler from being invoked when the event is raised, simply unsubscribe from the event. In order to prevent resource leaks, it is important to unsubscribe from events before you dispose of a subscriber object.

How to subscribe method in c#?

To subscribe to events by using the Visual Studio IDEOn top of the Properties window, click the Events icon. Double-click the event that you want to create, for example the Load event. Visual C# creates an empty event handler method and adds it to your code. Alternatively you can add the code manually in Code view.


2 Answers

I'm adding this in all the duplicate questions, just for the record. This pattern worked for me:

myClass.MyEvent -= MyHandler; myClass.MyEvent += MyHandler; 

Note that doing this every time you register your handler will ensure that your handler is registered only once.

like image 64
alf Avatar answered Sep 18 '22 01:09

alf


If you are talking about an event on a class that you have access to the source for then you could place the guard in the event definition.

private bool _eventHasSubscribers = false; private EventHandler<MyDelegateType> _myEvent;  public event EventHandler<MyDelegateType> MyEvent {    add     {       if (_myEvent == null)       {          _myEvent += value;       }    }    remove    {       _myEvent -= value;    } } 

That would ensure that only one subscriber can subscribe to the event on this instance of the class that provides the event.

EDIT please see comments about why the above code is a bad idea and not thread safe.

If your problem is that a single instance of the client is subscribing more than once (and you need multiple subscribers) then the client code is going to need to handle that. So replace

not already subscribed

with a bool member of the client class that gets set when you subscribe for the event the first time.

Edit (after accepted): Based on the comment from @Glen T (the submitter of the question) the code for the accepted solution he went with is in the client class:

if (alreadySubscribedFlag) {     member.Event += new MemeberClass.Delegate(handler); } 

Where alreadySubscribedFlag is a member variable in the client class that tracks first subscription to the specific event. People looking at the first code snippet here, please take note of @Rune's comment - it is not a good idea to change the behavior of subscribing to an event in a non-obvious way.

EDIT 31/7/2009: Please see comments from @Sam Saffron. As I already stated and Sam agrees the first method presented here is not a sensible way to modify the behavior of the event subscription. The consumers of the class need to know about its internal implementation to understand its behavior. Not very nice.
@Sam Saffron also comments about thread safety. I'm assuming that he is referring to the possible race condition where two subscribers (close to) simultaneously attempt to subscribe and they may both end up subscribing. A lock could be used to improve this. If you are planning to change the way event subscription works then I advise that you read about how to make the subscription add/remove properties thread safe.

like image 25
Hamish Smith Avatar answered Sep 19 '22 01:09

Hamish Smith