C # to prevent event handler interception twice

Duplicate: How to ensure that an event is signed only once and Has an event handler been added?

I have a singleton that provides some service, and my classes connect to some events on it, sometimes the class connects to the event twice and then gets called twice. I am looking for a classic way to prevent this. for some reason I need to check if I am connected to this event ...

+73
c # event-handling delegates
Jun 01 '09 at 22:46
source share
10 answers

Explicitly implement the event and check the call list. You also need to check the null value:

using System.Linq; // Required for the .Contains call below: ... private EventHandler foo; public event EventHandler Foo { add { if (foo == null || !foo.GetInvocationList().Contains(value)) { foo += value; } } remove { foo -= value; } } 

Using the code above, if the caller joins the event several times, he will simply be ignored.

+117
Jun 01 '09 at 22:58
source share

How to simply delete an event first with -= , if it is not found, no exception is thrown

 /// -= Removes the event if it has been already added, this prevents multiple firing of the event ((System.Windows.Forms.WebBrowser)sender).Document.Click -= new System.Windows.Forms.HtmlElementEventHandler(testii); ((System.Windows.Forms.WebBrowser)sender).Document.Click += new System.Windows.Forms.HtmlElementEventHandler(testii); 
+139
Jul 09 '09 at 14:33
source share

I tested every solution, and the best (considering performance):

 private EventHandler _foo; public event EventHandler Foo { add { _foo -= value; _foo += value; } remove { _foo -= value; } } 

Without using Linq. There is no need to check the null value before canceling the subscription (for more details see MS EventHandler). Don't forget to do bans everywhere.

+19
Jun 20 '13 at 20:15
source share

You really have to handle this at the sink level, not at the source level. That is, do not prescribe the logic of the event handler in the event source - leave this to the handlers (sinks) themselves.

As a service developer, who do you say that receivers can only register once? What if they want to register twice for some reason? And if you are trying to fix errors in the receivers by changing the source code, this again is a good reason to fix these problems at the receiver level.

I am sure that you have your own reasons; the source of events for which duplicate shells are illegal is not incomprehensible. But perhaps you should consider an alternative architecture that leaves the event semantics intact.

+17
Jun 01 '09 at 23:38
source share

You need to implement the addition and removal of accessories in the event, and then check the target list of the delegate or save the targets in the list.

In the add method, you can use the Delegate.GetInvocationList method to get a list of goals already added to the delegate.

Since delegates are defined to compare peers, if they are associated with the same method on the same target, you could probably go through this list and compare, and if you don't find any that compare it, you will add new.

Here is a sample code compiled as a console application:

 using System; using System.Linq; namespace DemoApp { public class TestClass { private EventHandler _Test; public event EventHandler Test { add { if (_Test == null || !_Test.GetInvocationList().Contains(value)) _Test += value; } remove { _Test -= value; } } public void OnTest() { if (_Test != null) _Test(this, EventArgs.Empty); } } class Program { static void Main() { TestClass tc = new TestClass(); tc.Test += tc_Test; tc.Test += tc_Test; tc.OnTest(); Console.In.ReadLine(); } static void tc_Test(object sender, EventArgs e) { Console.Out.WriteLine("tc_Test called"); } } } 

Output:

 tc_Test called 

(i.e. only once)

+12
Jun 01 '09 at 22:54
source share

The Microsoft Reactive Extensions (Rx) framework can also be used to "subscribe only once."

Given the mouse event foo.Clicked, here's how to subscribe and receive only one call:

 Observable.FromEvent<MouseEventArgs>(foo, "Clicked") .Take(1) .Subscribe(MyHandler); ... private void MyHandler(IEvent<MouseEventArgs> eventInfo) { // This will be called just once! var sender = eventInfo.Sender; var args = eventInfo.EventArgs; } 

In addition to providing “subscribe once” functionality, the RX approach offers the ability to compile events together or filter events. This is pretty elegant.

+6
Aug 13 '10 at 14:28
source share

Create an action instead of an event. Your class might look like this:

 public class MyClass { // sender arguments <----- Use this action instead of an event public Action<object, EventArgs> OnSomeEventOccured; public void SomeMethod() { if(OnSomeEventOccured!=null) OnSomeEventOccured(this, null); } } 
+1
Jun 19 '13 at 14:35
source share

you have a singleton object, check its list of who it is notifying, and only called once if it is duplicated. Alternatively, if possible, reject the request to join the event.

0
Jun 01 '09 at 22:56
source share

Maybe my answer to a similar post will help:

Differentiation between events caused by user interaction and my own code

0
Jun 01 '09 at 23:00
source share

In silverlight you should say e.Handled = true; in the event code.

 void image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { e.Handled = true; //this fixes the double event fire problem. string name = (e.OriginalSource as Image).Tag.ToString(); DoSomething(name); } 

Please mark me if this helps.

0
Aug 23 '12 at 18:24
source share



All Articles