【问题标题】:How to clear memoryleak from ElementHost Control如何从 ElementHost 控件中清除内存泄漏
【发布时间】:2014-07-18 10:41:44
【问题描述】:

我需要在 Winform 用户控件上托管 WPF 控件。为此,我使用了 ElementHost 控件。当我运行 Ants Memory profiler 时,我知道 ElementHost 控件中存在巨大的内存泄漏。请在下面找到随附的保留图,并帮助我修复 Memoryleak .

【问题讨论】:

  • 内存泄漏并不总是像 .NET 这样的托管环境中的样子。 “管理”一词在这里至关重要。有时,它只是一大块托管内存。你面临什么真正的问题?

标签: c# wpf elementhost


【解决方案1】:

这看起来像是某种已知的 WinForms 问题,cachedLayoutEventArgs 泄漏。根据我的经验,在 Windows 窗体中存在一些情况,当处置的控件可以缓存在 LayoutEventArgs 中时,它会阻止它被正确收集。详情请查看Windows Forms Memory Leak 线程。

我建议您在释放控件时尝试显式调用PerformLayout() 方法,包含您的ElementHost 或遵循WPF element host memory leak 线程中的recomendation

【讨论】:

    【解决方案2】:

    我遇到了完全相同的内存泄漏情况,症状完全相同。以下是我处理这种情况的方法。

    ElementHost 类具有PropertyMap 属性,该属性是将 WinForms 控件属性映射到 WPF 控件属性的集合。

    在这种特殊情况下,内存通过保存 MemoryStream 实例的 BackgroundImage 泄漏。 因此,解决方案是删除 BackgroundImage 属性映射:

    elementHost.PropertyMap.Remove("BackgroundImage");
    

    【讨论】:

    • 你救了我的培根!我遇到了一个问题,我在 TabControl + 上有一个 ElementHost ,每次我退出和返回时,我都会出现内存泄漏。原来这是罪魁祸首!谢谢伙计!我担心我正在进入一个痛苦的世界!
    【解决方案3】:

    我将从创建您自己的 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;
    }
    

    如果没有任何代码提示提示,很难说出问题出在哪里,但这将是一个不错的起点

    【讨论】:

      【解决方案4】:

      只是为了扩展 Vadim 的答案。我在 TabbedControl 上有一个 ElementHost ,每次我回到它时,都会发生内存泄漏。发生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
      

      GC.Collects 可能是矫枉过正?没有把握。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-12-27
        • 1970-01-01
        • 2019-05-22
        • 1970-01-01
        • 1970-01-01
        • 2021-07-13
        • 2015-10-14
        相关资源
        最近更新 更多