2010-05-08 16 views
8

Estoy creando muchos controles personalizados y los estoy agregando a un FlowLayoutPanel. También hay un ContextMenuStrip creado y poblado en el momento del diseño.Fuga de memoria con ContextMenuStrip

Cada vez que se agrega un control al panel, tiene su propiedad ContextMenuStrip asignada a este menú, de modo que todos los controles "comparten" el mismo menú. Pero noté que cuando los controles se quitan del panel y se eliminan, la memoria en uso en el Administrador de tareas no se cae. Se eleva alrededor de 50kB cada vez que se crea un control y se agrega al panel de diseño.

Descargué la versión de prueba de .NET Memory Profiler y mostró que había referencias a la tira del menú que colgaba después de que los controles fueron eliminados. Cambié el código para establecer explícitamente la propiedad ContextMenuStrip en null antes de deshacerme del control, y sí, ahora la memoria se ha liberado. ¿Por qué es esto? ¿No debería el GC limpiar este tipo de cosas?

+0

http://connect.microsoft.com/VisualStudio/feedback/details/116059/contextmenustrip-memory-leak – CharithJ

Respuesta

5

Si echas un vistazo a la propiedad ContexmenuStrip de Control, verás que el colocador suscribe el control al evento Disposed de MenuStrip, creando una retro-referencia desde MenuStrip al Control.

Esto significa que es un caso clásico de acceso a través del evento y que ya encontró la solución: establezca la propiedad ContexmenuStrip en nulo.

+0

Gracias Henk. Soy nuevo en C#, pero entérate de lo que quieres decir. ¿Pero por qué se está ocupando tanta memoria? Después de descubrir esta fuga, me di cuenta de que no estaba cancelando la suscripción a algunos eventos personalizados en mis propias clases antes de destruir las instancias. Y sin embargo, eso no parecía estar causando un aumento en el consumo de memoria. ¿O es una bestia diferente? – Dave

+1

Tenga en cuenta que es asimétrico, si hubiera Disposed the ContextMenu, no habría ningún problema. Considero que esto es un probable error de diseño de ContextMenuStrip, es astuto retroceder de este modo. Ten cuidado con eso en tus propias clases. Pero cuando una clase de suscripción está Dispuesta no hay problema. –

+0

Oh, está bien. Gracias. Supongo que este es un problema raro en el framework .net entonces? Sin el uso de un generador de perfiles de memoria, probablemente no habría captado este pequeño demonio. – Dave

0

Siempre debe desechar ContextMenuStrip en caso de que lo cree dinámicamente cada vez. Esto se debe a que cada vez se crea un identificador nativo, pero no se destruye. Esto significa que si crea un menú contextual y lo muestra, luego ciérrelo y muéstrelo de nuevo; se le acabarán las asas.