2010-05-30 9 views
9

Tengo una aplicación Windows Form en la que hacer clic en ciertos botones crea objetos a partir de un 2º formulario. Al cerrar este segundo formulario por el usuario, la memoria utilizada por este formulario no se libera (de acuerdo con el Administrador de tareas).this. Dispose() no libera la memoria utilizada por Form después de cerrarla.

He intentado utilizar this.dispose() el botón de salida, this.close(), form2 = null en el código principal, y trataron de despejar todos los controles de esta forma con el código antes de desecharlas. Nada de esto ha funcionado y cada vez que el usuario hace clic en el botón, el uso de memoria de la aplicación aumenta y la memoria utilizada por la instancia anterior no se libera.

¿Qué debo usar para resolver este problema?

+2

¿Está buscando una forma de liberar memoria asignada por un objeto secundario del formulario?Una clase de formulario simple tiene un consumo de memoria tan bajo que no puedo imaginar a nadie haciendo una publicación en el foro con respecto a esto ... –

Respuesta

17

Llamar a Dispose no limpiará la memoria utilizada por un objeto. Dispose está destinado a ejecutar código definido por el usuario que libera recursos que no se liberan automáticamente, como identificadores de archivos, identificadores de red, conexiones de bases de datos, etc.

Probablemente el culpable sea la segunda forma de adjuntar eventos a objetos que están fuera (¿quizás la primera forma?) y nunca desacoplarlos.

Si tiene algún evento en el segundo formulario, desactívelo en su sobrescritura OnClose, que hará que el segundo formulario sea elegible para la recolección de elementos no utilizados.

Nota, el recolector de basura .NET es bastante impredecible y podría crear algunas instancias de un objeto antes de limpiar todas las instancias anteriores que fueron elegibles para la recopilación. Una manera de saber con seguridad (sin recurrir a los perfiladores de memoria) es poner un punto de interrupción en el finalizador:

public class MyForm : Form { 
    ~MyForm() { 
    //breakpoint here 
    } 
} 

Si el finalizador se llama a continuación, esta clase está bien, si no, todavía tiene una fuga. También puede dar GC una "patada" - pero sólo para solucionar problemas - no abandonan este código en la producción - iniciando GC:

GC.Collect(); 
GC.WaitForPendingFinalizers(); 
GC.Collect(); 

poner el código anterior en alguna parte que se ejecuta después de cerrar y disponer el segunda forma. Debería llegar al punto de interrupción en el finalizador MyForm.

+0

Demasiado bueno. Tu respuesta me ayudó mucho. Gracias :) – EgyEast

+0

Seguí estas sugerencias, pero incluso después de poner el código de GC, mi función de finalización de formulario no está llegando a su punto de corte. Tengo una mala pérdida de memoria, parece. Estoy usando OpenTK en un Formulario separado con OpenGL, ¿quizás es eso? – theJerm

+0

Es por eso que me gusta C++ más. – Baso

0

Parece que la memoria todavía se está utilizando porque el recolector de basura no ha recuperado el objeto eliminado. Intente utilizar el método estático GC.Collect() para forzar una recolección de basura. Tenga cuidado con los problemas de rendimiento ya que esto normalmente detiene su programa hasta que haya terminado.

GC.Collect(); 
3

Dispose no es para liberar la memoria - recolector de basura del tiempo de ejecución de lenguaje común se encarga de eso. Dispose es para liberar otros recursos escasos (que no son de memoria), como las conexiones de bases de datos y los identificadores de archivos.

En general, no necesita preocuparse por el consumo de memoria en sus aplicaciones .NET porque el framework lo hace por usted. Si necesita un control más preciso sobre el consumo de memoria, debe desarrollar en un lenguaje que proporcione ese control, como C++.

-1

No llame al método Dispose(), llame a >>>>> Dispose (true) en su lugar y se sorprenderá mucho. En realidad, liberando memoria, puede observar un efecto en el administrador de tareas.

+0

'Dispose()' llama a 'Dispose (true) '. Ese es un método protegido; no deberías llamar eso. – SLaks

+0

Sí, está protegido, no es privado. Entonces no hay razón para no llamarlo. Dispose (bool disposing) se ejecuta en dos escenarios distintos. Si la eliminación es verdadera, el método ha sido llamado directa o indirectamente por un código de usuario. Los recursos administrados y no administrados pueden ser eliminados. Si disponer es igual a falso, el tiempo de ejecución ha llamado al método desde el finalizador y no debe hacer referencia a otros objetos. Solo los recursos no administrados pueden ser eliminados. © MSDN – Wallstrider

+0

'Dispose()' llamadas 'Dispose (true)'. El método interno es un detalle de implementación y no debe invocarse directamente. – SLaks

Cuestiones relacionadas