XP 上的 WPF 内存泄漏(CMilChannel,HWND)

Posted

技术标签:

【中文标题】XP 上的 WPF 内存泄漏(CMilChannel,HWND)【英文标题】:WPF Memory Leak on XP (CMilChannel, HWND) 【发布时间】:2010-12-14 22:03:58 【问题描述】:

我的 WPF 应用程序以大约 4kb/s 的速度泄漏内存。任务管理器中的内存使用量不断攀升,直到应用程序因“内存不足”异常而崩溃。

通过自己的研究,我发现这里讨论了这个问题:Track down memory leak in WPF 和 #8 这里:http://blogs.msdn.com/jgoldb/archive/2008/02/04/finding-memory-leaks-in-wpf-based-applications.aspx

描述的问题是: 这是 .NET 3.5 SP1 及之前的框架版本中存在的 WPF 漏洞。这是因为 WPF 选择使用哪个 HWND 将消息从呈现线程发送到 UI 线程的方式。此示例销毁创建的第一个 HWND 并在新窗口中启动动画。这会导致从渲染线程发送的消息堆积而不被处理,从而导致内存泄漏。

提供的解决方案是: 解决方法是首先在您的 App 类构造函数中创建一个新的 HwndSource。这必须在 WPF 创建任何其他 HWND 之前创建。只需创建这个 HwndSource,WPF 就会使用它来将消息从渲染线程发送到 UI 线程。这确保了所有消息都将被处理,并且不会泄漏。

但我不明白解决方案! 我有一个正在使用的 Application 子类,我尝试在该构造函数中创建一个窗口,但这并没有解决问题。

按照字面上给出的说明,看起来我只需要将其添加到我的应用程序构造函数中:

new HwndSource(new HwndSourceParameters("MyApplication"));

【问题讨论】:

我没有给你一个明确的答案,但这里有一个可能有帮助的事实:我发现只做一个“new HwndSource(...)”而不做其他事情(就像你如上所示)足以使 WPF 调用 RegisterClassEx 来进行子类化(Win32 称为子类化;而不是我们在 .NET 中所谓的“子类化”),并使用 CreateWindowEx 创建一个新的 hWnd。这会让我相信你上面写的那一行是克服你链接到的特定泄漏所必需的,所以问题可能出在其他地方。链接中的其他一些技术可能会有所帮助。 是的,我注意到简单地创建一个新的 HwndSource 是有益的,但这会产生一个很小的新空白窗口。我认为隐藏它可能和根本没有它一样糟糕。 HwndSourceParameters中不设置窗口标题,窗口停止出现,修复内存泄漏问题。 【参考方案1】:

修复:

Application.xaml.cs

class MyApp1 : Application

   // ...

   public Application()
   
       new HwndSource(new HwndSourceParameters());
   
   // ...

【讨论】:

以上是关于XP 上的 WPF 内存泄漏(CMilChannel,HWND)的主要内容,如果未能解决你的问题,请参考以下文章

防止 WPF 中的内存泄漏

WPF 列表框内存泄漏

WPF DataGrid ItemsSource 内存泄漏

绑定会在 WPF 中造成内存泄漏吗?

WPF DataGrid.items.Refresh() 内存泄漏

WPF应用程序内存泄漏的一些原因