简体   繁体   English

氪(Winforms 库)是否有可能存在 memory 泄漏问题

[英]Is it possible that Krypton (Winforms library) has memory leak issues

I' currently debugging a big Winforms application that's got some memory leak issues.我目前正在调试一个有一些 memory 泄漏问题的大型 Winforms 应用程序。 I use the .NET memory profiler and so far I've been able to find some of those leaks and solve them.我使用 .NET memory 分析器,到目前为止,我已经能够找到其中一些泄漏并解决它们。 But now I am faced with a problem which I am not sure is a problem, and if it is one I don't know how to solve it.但是现在我面临一个问题,我不确定是不是问题,如果是问题,我不知道如何解决。

After running my application for like 1 min (which is not a lot considering normal users could use it for hours),.NET memory profiler shows me around 100-200 instances of different controls from the Krypton Toolkit, and this number is increasing if I keep going (they are never garbage collected, because it appears they are still being referenced somewhere).在运行我的应用程序大约 1 分钟后(考虑到普通用户可以使用几个小时,这并不算多),.NET memory 分析器向我显示了来自 Krypton Toolkit 的大约 100-200 个不同控件的实例,如果我保持这个数字会增加去(它们永远不会被垃圾收集,因为看起来它们仍在某处被引用)。 Now if I check the root path of those instances and they all look like:现在,如果我检查这些实例的根路径,它们看起来都像:

Krypton ViewManager 的根路径

I don't know where to look in my code to make these instances be de-referenced correctly when they are not needed anymore, since I don't know what is still referencing the control.我不知道在我的代码中哪里可以在不再需要这些实例时正确地取消引用它们,因为我不知道什么仍在引用控件。 I know the place where the KryptonButtonEx gets created, and from what I understand the ViewManager is created by this button, but still I don't see what I can do about it.我知道创建 KryptonButtonEx 的位置,据我所知,ViewManager 是由这个按钮创建的,但我仍然不知道我能做些什么。 For those who are interested, the code to create the button is this:对于那些感兴趣的人,创建按钮的代码是这样的:

        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);

and even though it is not necessary from what my research told me, I unhook the event like this in the Dispose function:即使我的研究告诉我没有必要,我还是在 Dispose function 中解开了这样的事件:

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

So my question is:所以我的问题是:

Is it possible that Krypton itself keeps a reference to my controls which leads to some memory not being freed (which could be ok if it is a limited amount of memory used for keeping an object pool or something like that, but could be a problem if it is an uncontrolled memory leak)?氪本身是否有可能保留对我的控件的引用,这导致一些 memory 没有被释放(如果它是有限数量的 memory 用于保持 ZA8CFDE6331BD59EB66AC96F8911CCB 之类的东西,但可能是池或类似的东西,但可能是有限数量的 memory它是不受控制的 memory 泄漏)? If it doesn't come from Krypton, do you have an idea where to look to destroy those instances correctly?如果它不是来自 Krypton,您是否知道在哪里可以正确销毁这些实例?

Many thanks!非常感谢!

EDIT:编辑:

I just noticed that the class KryptonButtonEx doesn't come from Krypton but from my app.我刚刚注意到 class KryptonButtonEx 不是来自 Krypton,而是来自我的应用程序。 But I don't think it changes anything to the question since the only thing it does is override the GetPreferredSize function:但我认为它不会改变任何问题,因为它唯一要做的就是覆盖 GetPreferredSize function:

/// <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);
        }
    }
}

You posted the wrong code.您发布了错误的代码。 Instead of the code that creates the button, you should be very interested in the code that removes it.您应该对删除它的代码非常感兴趣,而不是创建按钮的代码。 Search for Controls.Remove and Controls.Clear and make sure that every control that is getting removed is being disposed.搜索 Controls.Remove 和 Controls.Clear 并确保正在释放每个要删除的控件。 Another diagnostic is TaskMgr.exe, Processes tab.另一个诊断是 TaskMgr.exe,进程选项卡。 View + Select Columns and tick USER objects.查看 + Select 列并勾选 USER 对象。 Seeing this number go up steadily is a hard clue that the code isn't disposing controls where is should.看到这个数字 go 稳步上升是一个硬线索,即代码没有将控件配置在应该在哪里。 This is the only case I know of not calling Dispose() causing a permanent leak.这是我知道的唯一不调用 Dispose() 导致永久泄漏的情况。

Instead of Controls.Clear(), use code like this:使用如下代码代替 Controls.Clear():

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

Disposing a control also automatically removes it from the parent's Controls collection.释放控件还会自动将其从父控件的集合中移除。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM