2010-12-09 13 views
11

Tengo un problema en el que una aplicación en la que estoy trabajando tiene pérdidas de memoria. La experiencia me ha enseñado que uno de los primeros lugares en los que los lenguajes recogidos de basura experimentan fugas de memoria es el de suscribirse a eventos y no cancelar su suscripción más tarde. El segundo tiene que ver con el almacenamiento de estado estático. Soy nuevo en C# y me he sentido frustrado por el tipo de evento opaco.¿Cómo averiguas qué está suscrito a un evento en C#?

Hemos atrapado algunos errores de suscripción doble por suerte, pero la aplicación realmente usa eventos para una serie de cosas. Si bien somos conscientes del principio de cancelar la suscripción de todo lo que suscribe, todavía hay pérdidas de memoria. Me gustaría determinar sistemáticamente qué está suscrito a qué.

Editar:

Gracias por el puntero al método GetInvocationList(). Estoy intentando crear un arnés de depuración que arrojará los resultados dinámicamente. El problema es que las soluciones que encontré funcionaban en .Net 2, pero ya no en .Net 3.5. Básicamente, le indica que obtenga el FieldInfo correspondiente para EventInfo (reflection, GetField y GetEvents, respectivamente). Sin embargo, en .Net 3.5 no hay FieldInfo correspondiente, y EventInfo no me permitirá obtener la lista de invocación.

Solo quiero descargar la lista de eventos y su InvocationList para fines de depuración.

+0

Consulte mi respuesta, C# Event Based Memory Leaks, a una pregunta similar del mes pasado. –

+0

Tuve un momento difícil para elegir cuál de los dos debería obtener la respuesta "oficial" porque ambos abordaron diferentes partes de mi necesidad. Al final elegí el que respondía la pregunta en el título, aunque la respuesta de n8wrl era igual de buena de diferentes maneras. –

Respuesta

6

Intente utilizar un método en el event llamado GetInvocationList.

Esto devolverá un conjunto de delegados que se suscriban al evento.

La matriz contendrá los delegados en el orden en que fueron agregados. Esto también se puede usar para seleccionar e invocar delegados específicos de la lista, mientras que llamar al método event.Invoke los invocará a todos (pero solo le dará el valor devuelto del último delegado llamado)

1

Sin duda tiene razón al sospechar la suscripción al evento como causa de 'fugas' en la memoria. Hace años rastreamos un problema en el que un objeto estático de toda la aplicación se suscribía a eventos de página ASP.NET; puede adivinar lo que sucedió allí.

Otra forma de abordar esto es desde la perspectiva del editor. Puede que no sea conveniente hacer que todos sus suscriptores se anulen, pero si el editor necesita ser destruido/fuera del alcance, tal vez se pueda desencadenar para anular todos sus eventos, borrando efectivamente a todos y rompiendo los bucles.

Si el editor tiene una vida útil más larga y es lo que mantiene vivos a otros objetos, es posible que tenga que hacer la tarea GetInvocationList sugerida anteriormente. Pero lo consideraría solo para depurar el problema, descubrir quién se aferra a los eventos cuando no deberían.

Last-resort podría considerar algún mecanismo de suscripción de evento personalizado basado en WeakReferenced.

+0

Esto también es muy útil.Veré cómo cablear los métodos Dispose() en los objetos que los tienen para borrar a los oyentes. Todavía necesito inspeccionar los resultados de manera eficiente. –

0

Vea this blog post para una forma clara de ver un volcado útil de los suscriptores de eventos en la ventana Inspección.

Cuestiones relacionadas