Derik Whittaker

Syndication

News


How to unsubscribe from an Event which is registered to an anonymous method

Anyone who has been doing any type of .net development knows you can subscribe (MSDN on event subscription) to an event as follows:

Subscribe to an Non-Anonymous Method

...

// instance class w/ an event
myClass.DoSomething += HandleDoSomething
...

// the method which handles the event
privat evoid HandleDoSomething( object s, args e )
{
// Logic goes here
}

Subscribe to an Anonymous Method

...

// instance class w/ an event
myClass.DoSomething += (s, e) => {
 		// logic goes here
	}

And to unsubscribe from a non-anonymous method you would do the following

...
// instance class w/ an event
myClass.DoSomething -= HandleDoSomething
...

However, the problem comes in when you try to unsubscribe to an event subscription which was wired up w/ an anonymous method.  You cannot do the following:

...
myClass.DoSomething -= (s, e) => {}
...

The reason the above does not work is that in order to unsubscribe to an event you need a memory pointer to a class instance.

However, there is a solution to our problem, you can do the following

EventHandler handler = null;

handler = (s, e) =>
{
	// time to do something useful here
        
	// the trick here is that you MUST un-subscribe inside your anonymous method.
	myClass.DoSomething -= handler;
};

	myClass.DoSomething += handler;

The reason the above works is because you have a class instance of our handler which we can use for both subscription and un-subscription.

Hope this helps.

Till next time


Posted 06-26-2011 9:20 AM by Derik Whittaker
Filed under: , ,

[Advertisement]

Comments

casino på nätet wrote re: How to unsubscribe from an Event which is registered to an anonymous method
on 06-27-2011 7:00 AM

These are helpful codes and links that is so fir for my site, Advance thank you for all of this one! Keep it up!

David Clarke wrote re: How to unsubscribe from an Event which is registered to an anonymous method
on 06-27-2011 5:30 PM

Have you tested that you must unsubscribe the handler inside the handler? Effectively by assigning the anonymous function to handler it loses its anonymity. You can unsubscribe as long as the handler is in scope, i.e. you can rewrite as:

EventHandler handler = (s, e) =>  

{  

   // time to do something useful here  

};  

myClass.DoSomething += handler;  

...

// unsubscribe

myClass.DoSomething -= handler;  

In the example you are actually creating a closure so the handler holds a reference to itself which can subsequently be used to unsubscribe from the event.

James C-S wrote re: How to unsubscribe from an Event which is registered to an anonymous method
on 06-28-2011 12:55 AM

I like the approach used by the Reactive Framework that joins the attach & detach operations into a single call that returns an `IDisposable` that is used to trigger the detach operation at some later point.

This allows many events, with different signatures, to be subscribed to and then I just have to hang on to a list of disposables that I can iterate through and dispose of later on. Also keeps all of the handler code together for easy refactoring.

Like this:

var disposables = new List<IDisposable>();

var myClass = new MyClass();

var subscription1 = Events.Subscribe(

   h => myClass.DoSomething += h,

   h => myClass.DoSomething -= h,

   (s, e) => { /* Do Action */ });

var subscription2 = myClass

   .DoSomethingSubscribe((s, e) => { /* Do Action */ });

disposables.Add(subscription1);

disposables.Add(subscription2);

myClass.OnDoSomething();

disposables.ForEach(d => d.Dispose());

public class MyClass

{

   public void OnDoSomething() { var ds = this.DoSomething; if (ds != null) ds(this, new EventArgs()); }

   public Subscriber DoSomethingSubscribe

   {

       get

       {

           return Events.Subscriber(

               h => this.DoSomething += h,

               h => this.DoSomething -= h);

       }

   }

   public event EventHandler DoSomething;

}

public delegate IDisposable Subscriber(EventHandler handler);

public static class Events

{

   public static IDisposable Subscribe(Action<EventHandler> attach, Action<EventHandler> detach, EventHandler handler)

   {

       if (attach == null) throw new ArgumentNullException("attach");

       if (detach == null) throw new ArgumentNullException("detach");

       if (handler == null) throw new ArgumentNullException("handler");

       attach(handler);

       return new AnonymousDisposable(() => detach(handler));

   }

   public static Subscriber Subscriber(Action<EventHandler> attach, Action<EventHandler> detach)

   {

       if (attach == null) throw new ArgumentNullException("attach");

       if (detach == null) throw new ArgumentNullException("detach");

       return (Subscriber)(h => Events.Subscribe(attach, detach, h));

   }

   internal sealed class AnonymousDisposable : IDisposable

   {

       private readonly Action Action;

       private int IsDisposed;

       public AnonymousDisposable(Action action)

       {

           if (action == null) throw new ArgumentNullException("action");

           this.Action = action;

       }

       public void Dispose()

       {

           if (Interlocked.Exchange(ref this.IsDisposed, 1) == 0)

           {

               this.Action();

           }

       }

   }

}

online casino wrote re: How to unsubscribe from an Event which is registered to an anonymous method
on 07-05-2011 3:02 AM

Can you make an Anonymous methods receive and return values?

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)