我需要在 Winform 用户控件上托管 WPF 控件。为此,我使用了 ElementHost 控件。当我运行 Ants Memory profiler 时,我知道 ElementHost 控件中存在巨大的内存泄漏。请在下面找到随附的保留图,并帮助我修复 Memoryleak 。
4 回答
它看起来像是某种已知的 WinFormscachedLayoutEventArgs
泄漏问题。根据我的经验,在 Windows 窗体中存在一些情况,当处置的控件可以缓存在其中时LayoutEventArgs
,它会阻止它被正确收集。查看Windows 窗体内存泄漏线程了解详细信息。
PerformLayout()
我建议您在处理控件时尝试显式调用该方法,包含您的ElementHost
或遵循WPF 元素主机内存泄漏线程的建议。
我遇到了完全相同的内存泄漏情况,症状完全相同。以下是我处理这种情况的方法。
ElementHost 类具有PropertyMap属性,该属性是将 WinForms 控件属性映射到 WPF 控件属性的集合。
在这种特殊情况下,内存通过保留 MemoryStream 实例的 BackgroundImage 泄漏。因此,解决方案是删除 BackgroundImage 属性映射:
elementHost.PropertyMap.Remove("BackgroundImage");
我将从创建您自己的 ElementHost 开始,覆盖 dispose,然后看看您是否可以看到那里的事件中的任何问题。查找调用 dispose 时仍然存在的处理程序。您可以在 dispose 方法中取消注册引用
public class MyElementHost : ElementHost
{
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if(disposing)
{
//Use debugging tools to identify handlers and unregister
MyEventHandler myEventHandler = (MyEventHandler)Delegate.CreateDelegate(typeof(MyEventHandler), this, "childElement_MyLeakingEvent");
FrameworkElement fe = Child as FrameworkElement;
if(fe != null)
fe.MyLeakingEvent -= myEventHandler;
}
}
Child = null;
Parent = null;
}
在没有任何代码提示的情况下很难说出问题出在哪里,但这将是一个不错的起点
只是为了扩展瓦迪姆的答案。我有ElementHost
一个 TabbedControl ,每次我回到它时,我都会遇到内存泄漏。蒸腾BackgroundImage
是罪魁祸首。以下解决方案适用于发现自己处于类似困境的任何人:
Private Sub BrushesEH_VisibleChanged(sender As Object, e As EventArgs) Handles BrushesEH.VisibleChanged
If BrushesEH.Visible = False Then
BrushesEH.PropertyMap.Remove("BackgroundImage")
GC.Collect()
Else
BrushesEH.PropertyMap.Reset("BackgroundImage")
GC.Collect()
End If
End Sub
s可能是GC.Collect
矫枉过正?没有把握。