6

I have a requirement to host WPF Control on Winform User control. To achieve this I used ElementHost control. When I run Ants Memory profiler , I got know that There is a Huge memory leak in the ElementHost control. Please find the attached retention graph as below and kindly help me to fix the Memoryleak .enter image description here

naveen
  • 1,451
  • 6
  • 21
  • 27

4 Answers4

2

I ran into exactly same memory leaking situation with exactly same symptoms. Here's how I handled the situation.

ElementHost class have PropertyMap property which is collection that maps WinForms control property to WPF control property.

In this particular case, memory is leaking through BackgroundImage that keeps MemoryStream instance. And so, the solution is to remove BackgroundImage property mapping:

elementHost.PropertyMap.Remove("BackgroundImage");
Vadim
  • 21
  • 2
  • you saved my bacon! I was having a problem where I had an `ElementHost` on a TabControl + every time I tabbed out and back, I would get a memory leak. Transpires this was the culprit! Thanks fella! I was worried that I was entering a world of pain! – stigzler Mar 16 '20 at 23:04
  • I can confirm this, except that BackgroundImage alone did not do the trick, I cleared the whole Property map: `elementHost.PropertyMap.Clear()` – Heinz Kessler Sep 02 '22 at 16:21
1

It looks like a some kind of known WinForms issue with cachedLayoutEventArgs leak. From my experience there are some situation in Windows Forms when disposed controls can be cached within the LayoutEventArgs and it prevents it from being collected properly. Take a look at Windows Forms Memory Leak thread for details.

I suggest you try to call the PerformLayout() method explicitly when disposing control, containing your ElementHost or follow the recomendation from the WPF element host memory leak thread.

Community
  • 1
  • 1
DmitryG
  • 17,677
  • 1
  • 30
  • 53
0

I would start with creating your own ElementHost, override dispose, and see if you can see any issues in the events there. Look for handlers that are still lying around when dispose gets called. You can unregister the references in the dispose method

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;
}

It is tough to say where the problem is without any code hint hint, but this would be a decent place to start

Matthew Frontino
  • 496
  • 2
  • 12
0

Just to expand upon Vadim's answer. I had an ElementHost on a TabbedControl and every time I tabbed back into it, i would get a memory leak. Transpires BackgroundImage was the culprit. Solution below for anyone who finds themselves in a similar predicament:

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

The GC.Collects are probably overkill? Not sure.

stigzler
  • 793
  • 2
  • 12
  • 29