Утечка памяти в ToolStrip
У меня были проблемы с утечками памяти с помощью SWF-ToolStrip. В соответствии с этим http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=115600 is был решен. Но здесь, похоже, нет.
Кто-нибудь знает, как решить эту проблему?
3 ответа
Эта проблема сохраняется в.NET 3.5 SP1, а также.NET 4.0.
Чтобы воспроизвести проблему, вы должны создать ToolStrip с большим количеством элементов, чем он может отобразить, что приводит к созданию кнопки переполнения. Проблема появляется только тогда, когда вы действительно нажимаете кнопку переполнения. При щелчке по нему создается объект ToolStripOverflow, который подписывается на событие Microsoft.Win32.UserPreferenceChangedEventHandler. ToolStrip не располагает объектом ToolStripOverflow, который приводит к тому, что обработчик событий не удаляется и вызывает утечку.
Это вызвало у нас огромные проблемы в большом приложении, которое создавало формы с ToolStrips.
Обходной путь - изменить метод Dispose формы или элемента управления, в котором размещается ToolStrip, следующим образом:
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);
}
Это решило это для нас
Private Sub frmBase_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Обрабатывает 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
Это удивительно постоянная жалоба. Источником утечки была ToolStrip, устанавливающая обработчик события для события SystemEvents.UserPreferenceChanged. Чтобы он мог реагировать на изменение пользователем темы или цветовой схемы и перерисовывать себя. Это статическое событие, если вы забудете отменить регистрацию обработчика события, это приведет к постоянной утечке экземпляра ToolStrip.
Ошибка определенно была исправлена в.NET 3.5 SP1. Метод ToolStrip.Dispose() отменяет регистрацию обработчика событий. Если это версия, которую вы используете, убедитесь, что метод Dispose () действительно работает. Распространенная ошибка - использовать Controls.Remove() для удаления элемента управления из формы, но затем забыть вызвать Dispose () для удаленного элемента управления.