【问题标题】:WeakReferences are not freed in embedded OS嵌入式操作系统中不释放弱引用
【发布时间】:2012-04-16 11:25:02
【问题描述】:

我在这里有一个奇怪的行为: 我在生产中运行 WPF 应用程序时遇到大量内存泄漏,该应用程序在 DLOG 终端(Windows Embedded Standard SP1)上运行,如果我在普通桌面(Win7 教授)上本地运行它,它的行为非常好。

在多次尝试发现任何问题均未成功后,我将其中一个直接放在显示器旁边,安装了 ANTs MemoryProfiler,并在终端和我的开发 PC 上模拟用户操作进行了一小时的测试运行。

结果是,由于一些奇怪的原因,嵌入式系统堆积了大量的 WeakReference 和 EffectiveValueEntry[] 对象。

这里有一些图片:

开发(PC):

还有终端:

只要看看班级列表...

以前有没有人见过这样的事情,是否有已知的解决方案? 我在哪里可以获得帮助?

(PS 安装了为 .net4 准备的图像的终端)

PPS:对于最接近的选民:我认为问题很明确:我该如何解决这个问题。 您可能会争论这是 IT/OS 问题还是编程问题,但我认为如果我将其发布在 Server Fault 中,它很快就会离题...

更新: 我能够找到问题的很大一部分——但感觉有点像 C++: 我为 WPF-List 使用类似 ViewModel 的 Items 类,它提供(以及其他)ICommand(RelayCommand-pattern)。在视图的 ViewModel-Property 的 getter 中动态创建的项目,似乎应用程序/GC 从未释放那些未使用的命令 - 或对其 CanExecuteChanged 的​​订阅 - 内存分析器将这些显示为“由弱参考”。我更改了我的代码以重用那些项目视图模型并将 Dispose/set 设置为 null 他们的 Dispose 中的每个使用的属性,并将其用作清理 - 正如我所说:在那些旧的 C++ 时代感觉就像“删除”。 最重要的是,我每 30 分钟使用一次强制 GC.Collect(是的,我知道 - 你永远不应该 - 但直到现在我没有其他解决方案)。 使用此设置,应用程序可以运行 6 多个小时,到目前为止没有任何问题,但感觉不对。

我不明白为什么这些 WeakReferences 没有像我的桌面计算机上那样被声明...

对此有什么想法吗?请!

更新: 我仍然无法确定这个问题,但我看到了一个奇怪的行为: 如果我使用 PC-Anywhere 观察我的软件在其中一个终端上的操作,问题就会消失! 即使在运行 8 小时后。软件直接运行 - 它甚至会释放内存(我在主屏幕上放了一个小内存计数器显示 - 假设我连接到终端并看到内存不足 - 等待几分钟后内存被回收)

所以我认为 Devin(下面的一个答案)在正确的方向上领先 - 远程控制软件中的某些东西解除了终结器线程或任何阻塞 GC 的东西 - 无论是模拟键盘/鼠标还是其他东西。

对此有什么想法吗?

【问题讨论】:

  • 这是一个在没有附加调试器的情况下运行 VB.NET 程序集的调试版本的已知问题。它泄漏了自动生成的弱引用,以跟踪 WithEvents 事件以支持 Edit+Continue。除此之外,不可能从屏幕截图中逆向工程代码。
  • 首先:这既不是 VB.NET 代码(无关紧要),也不是使用 DEBUG 集编译的 - 最重要的是,两者都在没有附加调试器的情况下运行,从同一版本开始使用相同的分析器,同时使用相同的程序集和文件(Xcopied)以及几乎相同的数据 - 你认为你可以从看到大量的 WPF 代码行中得到什么(或者你想要 all 代码 - 这是一些 MB 的文本文件......不是开源 BTW)
  • @HansPassant 提到的问题的参考(是的,VB.NET 在这里很重要):support.microsoft.com/?kbid=919481
  • 是的,谢谢 - 但正如我所说,这个正在运行的应用程序附近没有调试器,也没有使用 DEBUG 编译,而且 kb 只提到了 vs2005 和 vs2010,所以 也许 它得到了从那以后的3年内固定...
  • 我不明白为什么当您强制 GC.Collect(每 30 分钟)不强制它时会有所不同。如果您使用 ANTS 拍摄快照,它还会强制垃圾收集器运行,并且仍然存在具有“弱引用”的对象。你看过“实例保留图”吗?

标签: c# memory-leaks weak-references


【解决方案1】:

我们在平板电脑上运行我的应用时遇到了(有点)类似的问题。在桌面上运行时内存会被回收,但在平板电脑或其他使用 PC 输入面板的设备上运行时不会。问题是完成队列被卡住了。 COM 对象终结器正在等待在没有消息循环的主线程上运行某些东西。

解决方案是找到足够的时间来调用Application.DoEvents()。我们有一个会被间歇性调用的方法,我们每 10 次调用就调用它一次。我不知道这是否与您遇到的问题相同,但也许它可以提供一些启示。

编辑:我确实需要说清楚,总的来说,打电话给DoEvents() 是个坏主意。它在这种情况下有效,因为该线程上没有任何 UI 或这些事件可能会干扰的任何其他事件。

【讨论】:

  • 非常有趣-我会立即检查! - 顺便说一句:停用/关闭软件(?)键盘也解决了问题吗?我真的不需要设备上的键盘。
  • 如果我没记错的话,禁用键盘输入面板确实可以解决问题,但我不再拥有该设备,因此无法验证。
  • 检查了一段时间后,我不得不说:不,它不能解决问题。我删除了输入面板软件并尝试使用 WinForms-DoEvent 甚至手动 WPF-Dispatcher 调用 - 但感谢您的提示 - 我认为它指向了正确的方向。
  • 因为我认为这是朝着正确方向前进的方向,所以我会给予你应得的支持 - 谢谢
【解决方案2】:

从屏幕截图中有趣的是,LOH 在增长的同时使用的空间并没有增长太多。 LOH 处的可用空间增长很多,这表明由于固定对象导致内存碎片。这看起来像一个卡住的终结器线程,它确实阻止了托管对象的清理。你应该得到一个内存转储并检查终结器线程被卡住的方法。您可以使用 Windbg 轻松完成此操作。

【讨论】:

    猜你喜欢
    • 2015-05-09
    • 1970-01-01
    • 2012-07-12
    • 2012-03-09
    • 2010-09-11
    • 2011-10-07
    • 1970-01-01
    • 2018-03-26
    • 1970-01-01
    相关资源
    最近更新 更多