Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I unsubscribe from events? [duplicate]

I have 3 questions concerning events:

  1. Should I always unsubscribe events that were subscribed?
  2. What happens if I do NOT?
  3. In the below examples, how would you unsubscribe from the subscribed events?

I have for example this code:

Ctor: Purpose: For database property updates

this.PropertyChanged += (o, e) => {     switch (e.PropertyName)     {         case "FirstName": break;         case "LastName": break;     } }; 

and this: Purpose: For GUI-binding wrap the model into viewmodels

ObservableCollection<Period> periods = _lpRepo.GetDailyLessonPlanner(data.DailyDate); PeriodListViewModel = new ObservableCollection<PeriodViewModel>();  foreach (Period period in periods) {     PeriodViewModel periodViewModel = new PeriodViewModel(period,_lpRepo);     foreach (DocumentListViewModel documentListViewModel in periodViewModel.DocumentViewModelList)     {         documentListViewModel.DeleteDocumentDelegate += new Action<List<Document>>(OnDeleteDocument);         documentListViewModel.AddDocumentDelegate += new Action(OnAddDocument);         documentListViewModel.OpenDocumentDelegate += new Action<int, string>(OnOpenDocument);     }     PeriodListViewModel.Add(periodViewModel); } 
like image 795
Elisabeth Avatar asked Nov 13 '10 13:11

Elisabeth


People also ask

When to unsubscribe from event?

In order to prevent resource leaks, you should 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.

How do I unsubscribe from an event listener?

Event listeners can also be removed by passing an AbortSignal to an addEventListener() and then later calling abort() on the controller owning the signal.


2 Answers

Well, let's take the last question first. You can't reliably unsubscribe from an event that you've subscribed to directly with a lambda expression. You either need to keep a variable around with the delegate in (so you can still use a lambda expression) or you need to use a method group conversion instead.

Now as for whether you actually need to unsubscribe, it depends on the relationship between the event producer and the event consumer. If the event producer should live for longer than the event consumer, you should unsubscribe - because otherwise the producer will have a reference to the consumer, keeping it alive for longer than it should be. The event handler will also keep getting called for as long as the producer produces it.

Now in many cases that's not a problem - for example, in a form the button that raises the Click event is likely to live for about as long as the form on which it's created, where the handler is typically subscribed... so there's no need to unsubscribe. This is very typical for a GUI.

Likewise if you create a WebClient solely for the purpose of a single asynchronous request, subscribe to the relevant event and start the asynchronous request, then the WebClient itself will be eligible for garbage collection when the request has finished (assuming you don't keep a reference elsewhere).

Basically, you should always consider the relationship between the producer and the consumer. If the producer is going to live longer than you want the consumer to, or it's going to continue raising the event after you're no longer interested in it, then you should unsubscribe.

like image 124
Jon Skeet Avatar answered Sep 20 '22 08:09

Jon Skeet


1) It depends. Usually it's a good idea, but there are typical cases where you don't need to. Basically, if you are sure that the subscribing object is going to outlive the event source, you ought to unsubscribe, otherwise this would create an unnecessary reference.

If however your object is subscribing to its own events, like in the following:

<Window Loaded="self_Loaded" ...>...</Window> 

--then you don't have to.

2) Subscribing to an event makes additional reference to the subscribing object. So if you don't unsubscribe, your object might be kept alive by this reference, making effectively a memory leak. By unsubscribing you are removing that reference. Note that in the case of self-subscription the problem doesn't arise.

3) You can do like that:

this.PropertyChanged += PropertyChangedHandler; ... this.PropertyChanged -= PropertyChangedHandler; 

where

void PropertyChangedHandler(object o, PropertyChangedEventArgs e) {     switch (e.PropertyName)     {         case "FirstName": break;         case "LastName": break;     } } 
like image 32
Vlad Avatar answered Sep 23 '22 08:09

Vlad