c# .net event-handling system.reactive idisposable

c# - ¿Qué hacer con los IObservers que se eliminan?



.net event-handling (3)

Estoy usando Reactive Extensions para facilitar el manejo de eventos en mis ViewModels (aplicaciones Silverlight y / o Wp7). En aras de la simplicidad, digamos que tengo una línea como esta en el ctor de mi máquina virtual:

Observable.FromEvent<PropertyChangedEventArgs>( h => MyObject.PropertyChanged += h, h => MyObject.PropertyChanged -= h) .Where(e=>e.PropertyName == "Title") .Throttle(TimeSpan.FromSeconds(0.5)) .Subscribe(e=>{/*do something*/});

esto devuelve un objeto IDisposable, que si se elimina se cancelará. (¿Tengo razón en esta suposición?)
Si no hago referencia a él, tarde o temprano será recolectado y mi manejador será cancelado.

Normalmente tengo una List<IDisposable> en mi VM, y agrego suscripciones a ella, pero me siento sucio al respecto, como si no estuviera haciendo algo de la manera correcta de Rx.

¿Cuál es la mejor práctica, patrón recomendado en situaciones como esta?


Gideon es incorrecto aquí. La semántica de cómo Rx usa IDisposable es diferente de .NET típico. El IDisposable devuelto por Subscribe es si desea darse de baja antes del final de IObservable. Si no quiere hacer esto, es innecesario complicar su código con toda la administración desechable adicional.


Su primera suposición es correcta, la IDisposable es para darse de baja. Sin embargo, no es necesario que guardes una referencia al IDisposable para evitar que tu observador sea recogido. El IObservable necesitará mantener una referencia al observador para poder invocar sus métodos, manteniendo así al observador vivo mientras el observable esté vivo.

El lector astuto se dará cuenta de que estoy suplicando algo porque he supuesto que lo observable no se recogerá. Para lidiar con ese problema, hagamos algunas conjeturas razonables sobre lo que está sucediendo detrás de escena. El primer observable es suscribirse a un evento. Esto significa que el objeto con el evento tiene una referencia a nuestro observador desde el momento en que nos suscribimos hasta el momento en que cancelamos la suscripción. Como los operadores Rx deben en algún momento suscribirse a sus fuentes, se puede suponer que el observador del evento tiene una referencia al observador Where, que tiene una referencia al observador Throttle, que por supuesto se refiere a nuestro observador final.

Como no pudimos cancelar la suscripción, esto vincula la vida del observador con la vida del objeto con el evento. Sin un conocimiento completo de tu programa, eso es lo más avanzado que puedo llegar a la cadena, pero creo que debería ser suficiente para determinar la duración de la vida observable.

En realidad, esto indica una posible "pérdida de memoria" que puede tener con los eventos .NET estándar, objetos que mantienen vivos a todos sus suscriptores de eventos, lo que lleva a su segunda pregunta. Si no mantiene una referencia al IDisposable, nunca podrá darse de baja del evento y su objeto continuará recibiendo avisos, incluso después de cerrar la vista con la que está relacionado. Si el origen del evento no dura más que la vista, esto puede no ser un problema, pero recomiendo usar el desechable .

No hay nada "no-Rx" sobre esto, y Rx incluso incluye una buena clase para usar como alternativa a la Lista si lo desea, System.Reactive.Disposables.CompositeDisposable .


La práctica común es implementar una interfaz IDisposable y disponer de sus miembros desechables aquí.