26 out of 45 rated this helpful - Rate this topic

How to: Subscribe to and Unsubscribe from Events (C# Programming Guide)

You subscribe to an event that is published by another class when you want to write custom code that is called when that event is raised. For example, you might subscribe to a button's "click" event in order to make your application do something useful when the user clicks the button.

To subscribe to events by using the Visual Studio 2005 IDE

  1. If the Properties window is not visible, in Design view, right-click on the form or control for which you want to create an event handler, and select Properties.

  2. On top of the Properties window, click the Events icon.

  3. 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. For example, the following lines of code declare an event handler method that will be called when the Form class raises the Load event.

    private void Form1_Load(object sender, System.EventArgs e)
    {
        // Add your form load event handling code here.
    }
    
    

    The line of code that is needed to subscribe to the event is also automatically generated in the InitializeComponent method in the Form1.Designer.cs file in your project. It looks like this:

      this.Load += new System.EventHandler(this.Form1_Load);
    

To subscribe to events programmatically

  1. Define an event handler method whose signature matches the delegate signature for the event. For example, if the event is based on the EventHandler delegate type, then the following code represents the method stub:

      void HandleCustomEvent(object sender, CustomEventArgs a)
      {
         // Do something useful here.
      }
    
  2. Use the addition assignment operator (+=) to attach your event handler to the event. In the following example, assume that an object named publisher has an event named RaiseCustomEvent. Note that the subscriber class needs a reference to the publisher class in order to subscribe to its events.

    publisher.RaiseCustomEvent += HandleCustomEvent;
    

Note that the above syntax is new in C# 2.0. It is exactly equivalent to the C# 1.0 syntax in which the encapsulating delegate must be explicitly created using the new keyword:

publisher.RaiseCustomEvent += new CustomEventHandler(HandleCustomEvent);

To subscribe to events by using an anonymous method

  • Use the addition assignment operator (+=) to attach your anonymous method to the event. In the following example, assume that an object named publisher has an event named RaiseCustomEvent and that a CustomEventArgs class has also been defined to carry some kind of specialized event information. Note that the subscriber class needs a reference to publisher in order to subscribe to its events.

      publisher.RaiseCustomEvent += delegate(object o, CustomEventArgs e)
      {
        string s = o.ToString() + " " + e.ToString();
        Console.WriteLine(s);
      };
    

It is important to note that you cannot easily unsubscribe from an event if you used an anonymous method to subscribe to it. To unsubscribe in this scenario, go back to the code where you subscribe to the event, store the anonymous method in a delegate variable, and then add the delegate to the event.

Unsubscribing

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. Until you unsubscribe from an event, the multicast delegate that underlies the event in the publishing object has a reference to the delegate that encapsulates the subscriber's event handler. As long as the publishing object holds that reference, your subscriber object will not be garbage collected.

To unsubscribe from an event

  • Use the subtraction assignment operator (-=) to unsubscribe from an event:

      publisher.RaiseCustomEvent -= HandleCustomEvent;
    

    When all subscribers have unsubscribed from an event, the event instance in the publisher class is set to null.

See Also

Did you find this helpful?
(1500 characters remaining)
Community Content Add
Annotations FAQ
Events and Deadlocks

Events use internally multicast delegates when not manually implemented.

Two different locks occur while using these events:

  • The delegate is locked when raising an event and lasts until the execution returns from the event handler :
 myEvent(sender, args);  // myEvent is locked during the call
  • The delegate is locked when subscribing or unsubscribing from an event :
	myEvent += new EventHandler(HandlerMethod); // myEvent is locked during the operation

This behavior is hard to notice and can lead to deadlocks in multithreaded environements :

public class A
{
	public event EventHandler EventA;
	public event EventHandler EventB;


	public static void Main()
	{
		// subscribe to events
		EventA += new EventHandler(EventA_Handler);
		EventB += new EventHandler(EventB_Handler);

		// prepare threads
		Thread threadA = new Thread(new ThreadStart(MethodA));
		Thread threadB = new Thread(new ThreadStart(MethodB));

		// start threads
		threadA.Start();
		threadB.Start();

	}



	public void MethodA()
	{ 
		// called in threadA
		EventA(this, EventArgs.Empty);	// locks EventA in threadA
	}
  
	public void MethodB()
	{
		// called in threadB
		EventB(this, EventArgs.Empty);	// lock EventB in threadB
	}

  

  
	public void EventA_Handler(object sender, EventArgs e)
	{
		// called in threadA, EventA is locked by threadA
		// the following line tries to lock EventB in threadA
		EventB -= new EventHandler(EventB_Handler);
    
		// if threadB has entered the event handler,
		// EventB is already owned by threadB
		// the handler will not return until the lock is
		// released. But threadB will have the same problem
	}

    
	public void EventB_Handler(object sender, EventArgs e)
	{
		// called in threadB, EventB is locked by threadB
		// the following line tries to lock EventB in threadA
		EventA -= new EventHandler(EventA_Handler);
      
 		// if threadA has entered the event handler,
		// EventA is already owned by threadA
		// the handler will not return until the lock is
		// released.
		// There is a deadlock
	}
}

To prevent deadlocks, avoid subscribing or unsubscibing from events in event handlers or launch another thread that is not subject to the locks in order to subscribe or unsubscribe from the event. This alternative design makes the event subscription less predictive.

Advertisement