.net - GDI maneja en una aplicación DotNET
memory-leaks count (7)
Mi biblioteca DotNET pura se ejecuta como un complemento dentro de una aplicación de escritorio no administrada. He recibido un flujo constante (aunque bajo) de informes de fallos que parecen indicar un problema con los identificadores de GDI (fuentes en los mensajes de error, etc. vuelven a la fuente del sistema, se despliegan todo tipo de controles, falla masiva poco después )
Mis formularios tienen pocos controles, pero hago un montón de dibujo de GDI + en controles de usuario. ¿Cuál es una buena forma de decir cuántas manijas estoy usando o incluso goteando?
Gracias, David
Comenzando con GDIView de la respuesta de Ray Vega, encontré este consejo :
[DllImport("User32")]
extern public static int GetGuiResources(IntPtr hProcess, int uiFlags);
public static void GetGuiResourcesGDICount()
{
//Return the count of GDI objects.
Console.WriteLine("GDICount"+GetGuiResources(System.Diagnostics.Process.GetCurrentProcess().Handle, 0));
}
private void button1_Click(object sender, System.EventArgs e)
{
GetGuiResourcesGDICount();
}
GDIView informó que se trataba de objetos de fuentes que se estaban filtrando; Luego agregué llamadas a GetGuiResources
en nuestro código de registro para detectar en qué punto se activaba la creación del objeto.
En nuestro caso, teníamos el texto de un control Label
actualizado cuando su UserControl
padre estaba oculto en una ventana de fondo. Esto provocaría que GDI pierda identificadores de fuente. Para solucionarlo, cambiamos nuestra lógica para no actualizar la Label
menos que estuviera visible en la pantalla. Para determinar si era visible, guardamos un registro de cuándo fue pintado el UserControl
por última vez.
Además del monitor de rendimiento, puedes probar el viejo administrador de tareas.
Compruebe la pestaña Proceso y haga clic en View
> Select Columns...
y verifique los objetos GDI.
Es fácil de ver desde TaskMgr.exe, pestaña Procesos. Ver + Seleccionar columnas, marcar objetos GDI.
De hecho, su descripción coincide con una fuga de identificadores. Eso realmente no debería suceder en un programa administrado, el finalizador debería encargarse de que te olvides de llamar a Dispose (). A menos que no consuma una gran cantidad de espacio de montón recogido de basura. También podría ser la aplicación no administrada que se escapa maneja, lo hacen muy a menudo.
Si aún no lo hace, asegúrese de llamar IDisposable. Deseche en cualquier objeto de dibujo GDI + que esté utilizando. Por lo general, harías esto con la construcción con C #, por ejemplo:
using(Brush brush = ...)
{
...
}
Las herramientas de análisis de código estático como FxCop o la versión integrada en las ediciones de Visual Studio de Team System pueden ayudar a detectar casos en los que no se puede invocar a Dispose.
Si no se llama a Dispose de esta forma, se produce una posible fuga de identificador, ya que el identificador no se recuperará hasta que el recolector de basura lo considere oportuno.
Eche un vistazo a GDIView (es freeware):
GDIView es una herramienta única que muestra la lista de identificadores de GDI (pinceles, bolígrafos, fuentes, mapas de bits y otros) abiertos en cada proceso. Muestra el recuento total de cada tipo de identificador de GDI, así como información detallada sobre cada identificador. Esta herramienta puede ser útil para los desarrolladores que necesitan rastrear la fuga de recursos de GDI en su software.
texto alternativo http://www.nirsoft.net/utils/gdiview.gif
Tenga en cuenta que la actualización automática está deshabilitada de forma predeterminada, pero puede habilitarse y configurarse para intervalos específicos: Options -> Auto Refresh -> Every [N] seconds
He tenido que lidiar con el mismo tipo de problema en el pasado. Para inspeccionar cuántos objetos GDI está asignando su aplicación, puede usar una herramienta gratuita llamada GDIUsage .
En mi caso, la aplicación se bloqueaba porque estaba asignando más de 10.000 objetos GDI , que es un límite difícil en Windows XP. Puede valer la pena investigarlo.
He escrito sobre este problema aquí:
http://megakemp.com/2009/02/25/gdi-memory-leak-in-windows-forms/
GDIObj , una utilidad gratuita proporcionada por Feng Yuan como un programa de ejemplo para su libro, Windows Graphics Programming: Win32 GDI y DirectDraw podría ser útil.
A diferencia del Administrador de tareas, proporciona recuentos de un desglose adicional de diferentes tipos de identificador de GDI, incluidos DC, Región, Mapa de bits, Paleta, Fuente, Pincel, etc.
(Sin embargo, solo proporciona información de conteo mientras que GDIView proporciona más detalles sobre los identificadores).