ToolStrip 内存泄漏

4

我一直在使用SWF-ToolStrip时遇到内存泄漏的问题。根据这个链接,这个问题已经被解决了。但是在这里似乎还没有。

有人知道如何解决这个问题吗?


它是在哪个版本的.NET框架中解决的?您是否正在使用该版本? - Matt Breckon
我正在使用最新的 .Net 框架 3.5。但我们决定移除工具栏并使用其他控件来实现该功能,以避免内存问题。 - Marcus
3个回答

5
这个问题似乎在.NET 3.5 SP1和.NET 4.0中仍然存在。要重现该问题,您必须创建一个ToolStrip,并添加超过其能够显示的项,这会导致它创建一个溢出按钮。只有在您实际点击溢出按钮时才会出现问题。单击它会导致ToolStripOverflow对象被创建,该对象订阅Microsoft.Win32.UserPreferenceChangedEventHandler事件。 ToolStrip没有处理ToolStripOverflow对象,从而导致事件处理程序未被删除并导致泄漏。
这在一个创建了带有ToolStrip的窗体的大型应用程序中给我们带来了巨大的问题。
解决方法是更改托管ToolStrip的窗体或控件的Dispose方法,如下所示:
protected override void Dispose(bool disposing)
{

    if (disposing)
    {
        var overflow = toolStrip1.OverflowButton.DropDown as ToolStripOverflow;
        if (overflow != null)
            overflow.Dispose();
    }


    if (disposing && (components != null))
    {
        components.Dispose();
    }
    base.Dispose(disposing);
}

这对我们来说解决了问题。

1

私有子 frmBase_FormClosed(ByVal 作为对象 ByVal 发送者, ByVal e 作为 System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed

    ' .NET BUG WORKAROUND
    ' MANUALLY DISPOSE OF ToolStip, MenuStrip and StatusStrip to release memory being held
    Dim aNames As New ArrayList
    Dim count As Integer = 0

    For Each oItem As ToolStripItem In Me.MenuStrip1.Items
        aNames.Add(oItem.Name)
    Next

    For i As Integer = 0 To aNames.Count - 1
        For Each oItem As ToolStripItem In Me.MenuStrip1.Items
            If oItem.Name = aNames(i) Then
                oItem.Dispose()
                Exit For
            End If
        Next
    Next

    count = 0
    aNames.Clear()
    For Each oItem As ToolStripItem In Me.ToolStrip1.Items
        aNames.Add(oItem.Name)
    Next

    For i As Integer = 0 To aNames.Count - 1
        For Each oItem As ToolStripItem In Me.ToolStrip1.Items
            If oItem.Name = aNames(i) Then
                oItem.Dispose()
                Exit For
            End If
        Next
    Next

    count = 0
    aNames.Clear()
    For Each oItem As ToolStripItem In Me.StatusStrip1.Items
        aNames.Add(oItem.Name)
    Next

    For i As Integer = 0 To aNames.Count - 1
        For Each oItem As ToolStripItem In Me.StatusStrip1.Items
            If oItem.Name = aNames(i) Then
                oItem.Dispose()
                Exit For
            End If
        Next
    Next

    Me.MenuStrip1.Dispose()
    Me.ToolStrip1.Dispose()
    Me.StatusStrip1.Dispose()

End Sub

1
这是一个非常持久的抱怨。泄漏的源头是ToolStrip在SystemEvents.UserPreferenceChanged事件中安装了一个事件处理程序。这样它可以对用户更改主题或颜色方案做出响应并重新绘制自身。这是一个静态事件,忘记注销事件处理程序将永久泄漏ToolStrip实例。
在.NET 3.5 SP1中,这个错误肯定已被修复。ToolStrip.Dispose()方法将注销事件处理程序。如果您使用的是该版本,请确保Dispose()方法确实运行。一个常见的错误是使用Controls.Remove()从表单中移除控件,但却忘记在移除的控件上调用Dispose()方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接