ToolStrip memory leak

2020-03-24 08:56发布

I've been having trouble with memory leaks with the SWF-ToolStrip. According to this http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=115600# is has been resolved. But here it seemes not.

Anyone know how to resolve this?

3条回答
聊天终结者
2楼-- · 2020-03-24 09:25

This is a remarkably persistent complaint. The source of the leak was ToolStrip installing an event handler for the SystemEvents.UserPreferenceChanged event. So that it can respond to the user changing the theme or color scheme and redraw itself. This is a static event, forgetting to unregister the event handler will permanently leak the ToolStrip instance.

The bug has definitely been fixed in .NET 3.5 SP1. The ToolStrip.Dispose() method unregisters the event handler. If that's the version you are running, make sure that the Dispose() method indeed runs. A common mistake is to use Controls.Remove() to remove a control from a form but then forgetting to call Dispose() on the removed control.

查看更多
Explosion°爆炸
3楼-- · 2020-03-24 09:29

This problem seems to persist in .NET 3.5 SP1 as well as .NET 4.0.

To reproduce the problem you must create a ToolStrip with more items than it can display which causes it to create an overflow button. The problem only appears when you actually click the overflow button. Clicking it causes a ToolStripOverflow object to be created which subscribes to the Microsoft.Win32.UserPreferenceChangedEventHandler event. The ToolStrip doesn't dispose of the ToolStripOverflow object which causes the event handler to not be removed and causes a leak.

This caused us massive problems in a large app that created forms with ToolStrips on them.

A work around is to change the Dispose method of the form or control that hosts the ToolStrip as follows:

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

This solved it for us

查看更多
我想做一个坏孩纸
4楼-- · 2020-03-24 09:33

Private Sub frmBase_FormClosed(ByVal sender As Object, ByVal e As 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
查看更多
登录 后发表回答