5

アプリケーションのリソース リークをデバッグしていて、GDI オブジェクト リークをテストするテスト アプリを作成しました。OnPaint では、新しいアイコンと新しいビットマップを破棄せずに作成します。その後、ケースごとにタスク マネージャーで GDi オブジェクトの増加を確認します。ただし、アプリのメイン ウィンドウを再描画し続けると、アイコンの GDI オブジェクトの数が増えますが、ビットマップの変更はありません。アイコンがビットマップと同じようにクリーンアップされない特定の理由はありますか?

public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);

        // 1. icon increases number of GDI objects used by this app during repaint.
        //var icon = Resources.TestIcon;
        //e.Graphics.DrawIcon(icon, 0, 0);

        // 2. bitmap doesn't seem to have any impact (only 1 GDI object)
        //var image = Resources.TestImage;
        //e.Graphics.DrawImage(image, 0, 0);
    }
}

テスト結果:

  1. アイコンとビットマップなし - 30 個の GDI オブジェクト
  2. ビットマップ - 31 GDI オブジェクトでは、数値は変わりません。
  3. アイコン付き - 31 で、ウィンドウを再描画すると数が増えます。
4

1 に答える 1

1

アイコンは手動で処理する必要があると思います。検索を行ったところ、GC はビットマップを処理しますが、アイコンは処理しないことがわかりました。フォームは、アイコンの独自のコピーを保持することがあります (理由はわかりません)。アイコンを破棄する方法については、http: //dotnetfacts.blogspot.com/2008/03/things-you-must-dispose.htmlを参照してください。

[DllImport("user32.dll", CharSet = CharSet.Auto)]
extern static bool DestroyIcon(IntPtr handle);

private void GetHicon_Example(PaintEventArgs e)
{
// Create a Bitmap object from an image file.
Bitmap myBitmap = new Bitmap(@"c:\FakePhoto.jpg");

// Draw myBitmap to the screen.
e.Graphics.DrawImage(myBitmap, 0, 0);

// Get an Hicon for myBitmap.
IntPtr Hicon = myBitmap.GetHicon();

// Create a new icon from the handle.
Icon newIcon = Icon.FromHandle(Hicon);

// Set the form Icon attribute to the new icon.
this.Icon = newIcon;

// Destroy the Icon, since the form creates
// its own copy of the icon.
DestroyIcon(newIcon.Handle);
}
于 2015-04-02T16:02:07.050 に答える