G
Guest
hi there i've a test program that creates a treeview and destroys it over and
over,
i keep track of the gdi object count for the process and see if they are ok.
However when i switch on checkboxes for my test app i get a gdi handle leak
anyone got any ideas on this one?
over,
i keep track of the gdi object count for the process and see if they are ok.
However when i switch on checkboxes for my test app i get a gdi handle leak
anyone got any ideas on this one?
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace TreeViewMemoryLeak
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// get process
m_processHandle = GetCurrentProcess();
// update status
OnTimer_Tick(this, null);
}
private void OnStartStop_Click(object sender, EventArgs e)
{
// invert state
m_isRunning = !m_isRunning;
// disbale if running
m_chkUseCheckboxes.Enabled = !m_isRunning;
m_btnStartStop.Text = (m_isRunning) ? "Stop loop" : "Start
create / dispose loop";
// running?
if (m_isRunning)
{
// reset
m_lblSummary.Text = "";
m_treeViewCount = 0;
m_initialGdiCount = GetGuiResources(m_processHandle,
(uint)ResourceType.Gdi);
// loop
while (m_isRunning)
{
CreateDisposeTreeView();
++m_treeViewCount;
}
// how many GDI objects per tree view?
uint gdiObjects = GetGuiResources(m_processHandle,
(uint)ResourceType.Gdi) - m_initialGdiCount;
m_lblSummary.Text = string.Format(
"{0} TreeViews were created and disposed with a {1:0.0}
GDI objects leak per TreeView",
m_treeViewCount,
gdiObjects / (float)m_treeViewCount);
}
}
private void CreateDisposeTreeView()
{
// create
TreeView tvw = new TreeView();
tvw.Location = new Point(20, 20);
tvw.Size = new Size(100, 100);
tvw.CheckBoxes = m_chkUseCheckboxes.Checked;
m_pnlContainer.Controls.Add(tvw);
// do some gui processing
Application.DoEvents();
// dispose
m_pnlContainer.Controls.Remove(tvw);
tvw.Dispose();
tvw = null;
// do some gui processing
Application.DoEvents();
}
private void OnTimer_Tick(object sender, EventArgs e)
{
// update status bar
if (m_processHandle != IntPtr.Zero)
{
// memory
PROCESS_MEMORY_COUNTERS counters = new
PROCESS_MEMORY_COUNTERS();
GetProcessMemoryInfo(m_processHandle, out counters, 40);
m_sslMemory.Text = string.Format("Memory usage: {0:#,##0}
KBytes", counters.WorkingSetSize / 1024);
m_sslMemory.Invalidate();
// gdi
m_sslGdi.Text = string.Format("GDI Objects: {0}",
GetGuiResources(m_processHandle, (uint)ResourceType.Gdi));
m_sslGdi.Invalidate();
// objects
m_sslObjectCount.Text = string.Format("TreeViews: {0}",
m_treeViewCount);
m_sslObjectCount.Invalidate();
}
}
#region Win32 API functions
/// uiFlags: 0 - Count of GDI objects
/// uiFlags: 1 - Count of USER objects
/// - Win32 GDI objects (pens, brushes, fonts, palettes, regions,
device contexts, bitmap headers)
/// - Win32 USER objects:
/// - WIN32 resources (accelerator tables, bitmap resources,
dialog box templates, font resources, menu resources, raw data resources,
string table entries, message table entries, cursors/icons)
/// - Other USER objects (windows, menus)
///
[DllImport("user32.dll")]
private static extern uint GetGuiResources(IntPtr hProcess, uint
uiFlags);
private enum ResourceType
{
Gdi = 0,
User = 1
}
[DllImport("kernel32.dll")]
private static extern IntPtr GetCurrentProcess();
[DllImport("psapi.dll")]
private static extern int GetProcessMemoryInfo(IntPtr hProcess, out
PROCESS_MEMORY_COUNTERS counters, int size);
[StructLayout(LayoutKind.Sequential, Size=40)]
private struct PROCESS_MEMORY_COUNTERS
{
public int cb;
public int PageFaultCount;
public int PeakWorkingSetSize;
public int WorkingSetSize;
public int QuotaPeakPagedPoolUsage;
public int QuotaPagedPoolUsage;
public int QuotaPeakNonPagedPoolUsage;
public int QuotaNonPagedPoolUsage;
public int PagefileUsage;
public int PeakPagefileUsage;
}
#endregion
private IntPtr m_processHandle = IntPtr.Zero;
private bool m_isRunning = false;
private int m_treeViewCount = 0;
private uint m_initialGdiCount = 0;
}
}