son que programacion net mas los llamar invocar eventos evento event delegados comunes c# events subscribe unsubscribe

c# - que - ¿Debo cancelar mi suscripción a los eventos?



public event c# (5)

Esta pregunta ya tiene una respuesta aquí:

Tengo 3 preguntas sobre eventos:

  1. ¿Debo anular siempre la suscripción a los eventos que se suscribieron?
  2. ¿Qué pasa si NO?
  3. En los ejemplos a continuación, ¿cómo cancelaría la suscripción a los eventos suscritos?

Tengo, por ejemplo, este código:

Ctor: Propósito: Para actualizaciones de propiedades de la base de datos

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

y esto: Propósito: para el enlace GUI envuelva el modelo en 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); }


1) Depende Por lo general, es una buena idea, pero hay casos típicos en los que no es necesario. Básicamente, si está seguro de que el objeto suscrito va a sobrevivir al origen del evento, debe darse de baja, de lo contrario, esto crearía una referencia innecesaria.

Sin embargo, si su objeto se suscribe a sus propios eventos, como en el siguiente:

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

- Entonces no tienes que hacerlo.

2) La suscripción a un evento hace referencia adicional al objeto de suscripción. Por lo tanto, si no se da de baja, su objeto se mantendrá vivo con esta referencia, lo que lo convierte en una pérdida de memoria. Al desuscribirse, está eliminando esa referencia. Tenga en cuenta que en el caso de la auto-suscripción, el problema no surge.

3) Puedes hacer eso:

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

dónde

void PropertyChangedHandler(object o, PropertyChangedEventArgs e) { switch (e.PropertyName) { case "FirstName": break; case "LastName": break; } }


Bien, tomemos la última pregunta primero. No puede darse de baja de manera confiable de un evento al que se haya suscrito directamente con una expresión lambda. O necesita mantener una variable con el delegado en (por lo que aún puede usar una expresión lambda) o necesita usar una conversión de grupo de métodos.

Ahora, si realmente necesita darse de baja, depende de la relación entre el productor del evento y el consumidor del evento. Si el productor del evento debe vivir por más tiempo que el consumidor del evento, debe darse de baja, ya que de lo contrario el productor tendrá una referencia al consumidor, manteniéndolo con vida por más tiempo de lo que debería. El controlador de eventos también seguirá recibiendo llamadas mientras el productor lo produzca.

Ahora, en muchos casos, eso no es un problema, por ejemplo, en una forma el botón que genera el evento Click es probable que viva tanto tiempo como la forma en que se creó, donde el controlador está suscrito normalmente ... por lo que no hay necesidad de darse de baja Esto es muy típico para una GUI.

Del mismo modo, si crea un WebClient únicamente para una única solicitud asíncrona, se suscribe al evento relevante y comienza la solicitud asincrónica, entonces el WebClient mismo será elegible para la recolección de basura cuando la solicitud haya finalizado (suponiendo que no mantenga un referencia en otro lugar).

Básicamente, siempre debe considerar la relación entre el productor y el consumidor. Si el productor va a vivir más de lo que desea que el consumidor lo haga, o continuará provocando el evento una vez que ya no esté interesado en él, entonces debe darse de baja.


Puede echar un vistazo a este artículo en MSDN. Citar:

Para evitar que se invoque su controlador de eventos cuando se produce el evento, simplemente anule su suscripción del evento. Para evitar pérdidas de recursos, es importante darse de baja de los eventos antes de deshacerse de un objeto suscriptor. Hasta que se da de baja de un evento, el delegado de multidifusión que subyace al evento en el objeto de publicación tiene una referencia al delegado que encapsula el controlador de eventos del suscriptor. Siempre que el objeto de publicación contenga esa referencia, su objeto de suscriptor no será basura.


1.) ¿Debería siempre cancelar la suscripción de eventos suscritos?
Por lo general, sí. La única excepción es cuando el objeto al que se suscribió ya no se referencia y pronto se recolectará basura.

2.) ¿Qué pasa si NO?
El objeto en el que se suscribió tendrá una referencia al delegado, que a su vez contiene una referencia a su this puntero, y así obtendrá una pérdida de memoria.
O si el controlador era un lamda, se mantendrá en cualquier variable local que se vincule, que tampoco se recogerá.


No tiene que darse de baja de un evento cuando la instancia que se suscribe tiene el mismo alcance que la instancia a la que se está suscrito.

Digamos que eres un formulario y te estás suscribiendo a un control, estos dos forman un grupo. Sin embargo, si tiene una clase central que administra formularios y se ha suscrito al evento Closed de ese formulario, estos no forman un grupo juntos y debe darse de baja una vez que se cierra el formulario.

La suscripción a un evento hace que la instancia suscrita cree una referencia a la instancia a la que se está suscrito. Esto evita la recolección de basura. Por lo tanto, cuando tiene una clase central que administra instancias de formulario, esto mantendrá todas las formas en la memoria.

WPF es una excepción porque tiene un modelo de evento débil donde los eventos están suscritos utilizando referencias débiles y no mantendrá el formulario en la memoria. Sin embargo, sigue siendo una buena práctica darse de baja cuando no formes parte del formulario.