开发者

ToolStrip memory leak

I've been having trouble with开发者_如何学C 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?


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


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.


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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜