4

現在、メモリ リークの問題がある大きな Winforms アプリケーションをデバッグしています。私は .NET メモリ プロファイラーを使用しており、これまでのところ、これらのリークのいくつかを見つけて解決することができました。しかし今、私は問題であるかどうかわからない問題に直面しています。それが問題である場合、解決方法がわかりません。

アプリケーションを 1 分間実行した後 (通常のユーザーが何時間も使用できることを考えると、それほど長くはありません)、.NET メモリ プロファイラーは、クリプトン ツールキットからのさまざまなコントロールの約 100 ~ 200 のインスタンスを表示します。続行します (まだどこかで参照されているように見えるため、ガベージ コレクションは行われません)。これらのインスタンスのルート パスを確認すると、次のようになります。

Krypton ViewManager のルート パス

何がコントロールを参照しているのかわからないため、これらのインスタンスが不要になったときにこれらのインスタンスを正しく参照解除するためにコードのどこを調べればよいかわかりません。KryptonButtonEx が作成される場所を知っており、このボタンによって ViewManager が作成されていることを理解していますが、それでも何ができるかわかりません。興味のある方のために、ボタンを作成するコードは次のとおりです。

        KryptonButton newControlButton = new KryptonButton();
        newControlButton.Tag = mtActivityControl;
        newControlButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
        newControlButton.AutoSize = true;
        newControlButton.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowOnly;
        newControlButton.ButtonStyle = ComponentFactory.Krypton.Toolkit.ButtonStyle.ListItem;
        newControlButton.Location = new System.Drawing.Point(3, 3);
        newControlButton.Name = string.Format("controlButton{0}", mtActivityControl.SymbolicName);
        newControlButton.Size = new System.Drawing.Size(96, 23);
        newControlButton.StateCommon.Content.Image.ImageH = ComponentFactory.Krypton.Toolkit.PaletteRelativeAlign.Near;
        newControlButton.StateCommon.Content.ShortText.TextH = ComponentFactory.Krypton.Toolkit.PaletteRelativeAlign.Near;
        newControlButton.TabIndex = 5;

        StringBuilder buttonText = new StringBuilder();
        buttonText.Append(Path.GetFileName(mtActivityControl.ControlName));
        /*if (mtActivityControl.SymbolicName.Length != 0)
        {
            buttonText.Append(" (");
            buttonText.Append(mtActivityControl.SymbolicName);
            buttonText.Append(")");
        }*/

        newControlButton.Text = buttonText.ToString();
        newControlButton.Values.ExtraText = "";
        newControlButton.Values.Image = null;
        newControlButton.Values.ImageStates.ImageCheckedNormal = null;
        newControlButton.Values.ImageStates.ImageCheckedPressed = null;
        newControlButton.Values.ImageStates.ImageCheckedTracking = null;
        newControlButton.Values.Text = buttonText.ToString();
        newControlButton.Click += new System.EventHandler(this.controlsButton_Click);

私の調査によると必要ではありませんが、 Dispose 関数で次のようにイベントをフック解除します。

newControlButton.Click -= new System.EventHandler(this.controlsButton_Click);

だから私の質問は:

クリプトン自体が私のコントロールへの参照を保持していて、一部のメモリが解放されていない可能性はありますか (オブジェクト プールなどを保持するために使用されるメモリ量が限られている場合は問題ありませんが、次の場合は問題になる可能性があります)。それは制御されていないメモリリークです)?クリプトンから来ていない場合、それらのインスタンスを正しく破壊するためにどこを探すべきか考えていますか?

どうもありがとう!

編集:

クラス KryptonButtonEx が Krypton からではなく、私のアプリから来ていることに気付きました。しかし、それが行う唯一のことは GetPreferredSize 関数をオーバーライドすることなので、質問に何も変わらないと思います:

/// <summary>
/// An extended/fixed KryptonButton which handles resizing correctly.
/// </summary>
public class KryptonButtonEx : ComponentFactory.Krypton.Toolkit.KryptonButton
{
    /// <summary>
    /// Gets the size of the preferred.
    /// </summary>
    /// <param name="proposedSize">Size of the proposed.</param>
    /// <returns></returns>
    public override Size GetPreferredSize(Size proposedSize)
    {
        // Do we have a manager to ask for a preferred size?
        if (ViewManager != null)
        {
            // Ask the view to peform a layout
            Size retSize = ViewManager.GetPreferredSize(Renderer, proposedSize);

            // Apply the maximum sizing
            if (MaximumSize.Width > 0) retSize.Width = Math.Min(MaximumSize.Width, retSize.Width);
            if (MaximumSize.Height > 0) retSize.Height = Math.Min(MaximumSize.Height, retSize.Width);

            // Apply the minimum sizing
            if (MinimumSize.Width > 0) retSize.Width = Math.Max(MinimumSize.Width, retSize.Width);
            if (MinimumSize.Height > 0) retSize.Height = Math.Max(MinimumSize.Height, retSize.Height);

            return retSize;
        }
        else
        {
            // Fall back on default control processing
            return base.GetPreferredSize(proposedSize);
        }
    }
}
4

1 に答える 1

5

間違ったコードを投稿しました。ボタンを作成するコードではなく、ボタンを削除するコードに注目する必要があります。Controls.Remove および Controls.Clear を検索し、削除されるすべてのコントロールが破棄されていることを確認します。もう 1 つの診断は、TaskMgr.exe の [プロセス] タブです。表示 + 列を選択し、USER オブジェクトにチェックマークを付けます。この数値が着実に上昇していることは、コードがコントロールを配置すべき場所に配置していないことを示す難しい手がかりです。これは、Dispose() を呼び出さないと永続的なリークが発生する唯一のケースです。

Controls.Clear() の代わりに、次のようなコードを使用します。

 while (panel.Controls.Count > 0) panel.Controls[0].Dispose();

コントロールを破棄すると、親の Controls コレクションからも自動的に削除されます。

于 2011-05-27T13:08:45.703 に答える