WPF element host memory leak

2020-05-24 05:58发布

问题:

I'm having a strange memory leak using element host on windows forms. I have a main form, which opens another form, the one that only haves the elementhost control on it (which, at this point, does not have a wpf control child). Only 1 host form can be opened. Every time I open the form, the application memory raises by 20Mb, which are not free when the form is closes, so, after opening the host form several times, I run out of memory!. Now, if I remove the element host from the form, the memory remains stable.

I have been running CLRProfiler and ANTS, but I have found that all the problem resides on the element host, and I haven't found any workaround for this.

The wpfHost is used out-of-the-box, just dragged from the toolbar to the winForm.

Any idea how can I solve this?

回答1:

if the link will break again, here is solution (copy-pasted)

Posted by KGy on 22.10.2010 at 6:12 A possible workaround: Put the following code into the Dispose or another release method of your control/form that contains the ElementHost control.

if (elementHost != null)
{
    FrameworkElement fe = elementHost.Child as FrameworkElement;
    if (fe != null)
    {
        // Memory leak workaround: elementHost.Child.SizeChanged -= elementHost.childFrameworkElement_SizeChanged;
        SizeChangedEventHandler handler = (SizeChangedEventHandler)Delegate.CreateDelegate(typeof(SizeChangedEventHandler), elementHost, "childFrameworkElement_SizeChanged");
        fe.SizeChanged -= handler;
    }
    elementHost.Child = null;
    base.Dispose(disposing);
    elementHost.Dispose();
    elementHost.Parent = null;
    elementHost = null;
}


回答2:

The primary cause of "memory leaks" in .NET applications is event handlers. If object A handles an event raised by object B, object A can go out of scope and it won't be destroyed, because even though your code doesn't retain a reference to it, object B does.

In WinForms, some UI objects (ToolStripButton is a good example) register with Windows to handle theme-change events. Windows holds a reference to them so that it can tell them if the user changes the theme. Annoyingly, these objects don't unregister if the form they're on closes, with the result that their form gets destroyed but they don't.

So how the heck do you destroy one of these objects? In the case of ToolStripButton, setting Visible to false does the trick. It turns out that toggling Visible also toggles whether or not the control handles theme-change events. So if you set Visible to false, the control unregisters, and then when it goes out of scope it actually can get destroyed.

Maybe that will help with ElementHost, for the same or a similar reason. It's hard to tell, because as you'll find if you dig into this issue, it's not exactly, you know, documented.



回答3:

I have a WPF ElementHost Object on my form and noticed a memory leak as well. What I was doing was something like this:

VAR cnt=this.MyHostControl.Child as MyWPFControl.WPObject;

and would do this in scope IE:

Private void Myfunction()
{

   VAR cnt=this.MyHostControl.Child as MyWPFControl.WPObject;
   cnt.Myproerty="Issue";

}

Not being a big fan of a VAR (Reminds of old COM days), I decided to create a global object like this:

MyWPFControl.WPObject cnt = null;

Then on the FormLoad_EvenT()

I initialized the object cnt like so:

cnt = this.MyHostControl.Child as MyWPFControl.WPObject;

Now my reference looks like this:

Private void Myfunction()
{

   cnt=this.MyHostControl.Child as MyWPFControl.WPObject;
   cnt.Myproerty="Issue";

}

And I do not need to create a var object.

Still testing and it looks like it maybe working. We will see over time.