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
精彩评论