WPF元素主机内存泄漏

本文关键字:泄漏 内存 主机 元素 WPF | 更新日期: 2023-09-27 17:59:14

我在windows窗体上使用元素host时发生了一个奇怪的内存泄漏。我有一个主窗体,它打开了另一个窗体,这个窗体上只有elementhost控件(目前没有wpf控件的子窗体)。只能打开一个主机窗体。每次打开表单时,应用程序内存都会增加20Mb,当表单关闭时,这些内存是不可用的,所以,在多次打开主机表单后,我的内存就用完了!。现在,如果我从表单中删除元素host,那么内存将保持稳定。

我一直在运行CLRProfiler和ANTS,但我发现所有的问题都存在于元素主机上,我还没有找到任何解决方法。

wpfHost是开箱即用的,只需从工具栏拖动到winForm即可。

知道我该怎么解决这个问题吗?

WPF元素主机内存泄漏

如果链接将再次断开,这里是解决方案(复制粘贴)

KGy于2010年10月22日6:12发布一种可能的解决方法:将以下代码放入包含ElementHost控件的控件/窗体的Dispose或其他发布方法中。

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

中"内存泄漏"的主要原因。NET应用程序是事件处理程序。如果对象A处理对象B引发的事件,则对象A可能超出范围,并且不会被销毁,因为即使您的代码没有保留对它的引用,对象B也会保留。

在WinForms中,一些UI对象(ToolStripButton就是一个很好的例子)向Windows注册以处理主题更改事件。Windows保存了对它们的引用,以便在用户更改主题时告诉它们。令人烦恼的是,如果这些对象所在的窗体关闭,它们就不会注销,结果是它们的窗体被破坏,但它们没有。

那么,你是如何摧毁其中一个物体的呢?在ToolStripButton的情况下,将Visible设置为false即可。事实证明,切换Visible还切换控件是否处理主题更改事件。因此,如果将Visible设置为false,则控件将注销,然后当它超出范围时,它实际上可能会被销毁。

也许这将有助于ElementHost,出于相同或类似的原因。这很难说,因为如果你深入研究这个问题,你会发现它并没有被记录在案。

我的表单上有一个WPF ElementHost对象,并注意到内存泄漏。我正在做的事情是这样的:

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

并将在范围IE:中执行此操作

Private void Myfunction()
{
   VAR cnt=this.MyHostControl.Child as MyWPFControl.WPObject;
   cnt.Myproerty="Issue";
}

由于不是VAR(让人想起以前的COM时代)的铁杆粉丝,我决定创建一个这样的全局对象:

MyWPFControl.WPObject cnt = null;

然后在FormLoad_EvenT()

我初始化对象cnt,如下所示:

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

现在我的参考如下:

Private void Myfunction()
{
   cnt=this.MyHostControl.Child as MyWPFControl.WPObject;
   cnt.Myproerty="Issue";
}

并且我不需要创建var对象。

仍在测试中,看起来可能有效。随着时间的推移,我们会看到的。