4

应用背景

我们的平台是一个点击一次的 WPF 应用程序。我们有一个包含导航菜单结构的“shell”,它托管我们自己的自定义“页面”类。当您导航到新页面时,我们会(基本上)换掉 shell 的内容。

问题

所以,我为一家从事大型软件项目的公司工作。我们发现有很多代码存在内存问题。

问题是在我们的应用程序中有很多地方是事件是有线的而不是无线的。我不确定开发人员为什么要这样做,我猜他们希望每次用户导航到新的“页面”时都会清理对象。

我们没有重构每个页面的选项(在此版本中)。C# 有没有办法从对象中删除所有引用?(因此允许垃圾收集器将该对象连同它的所有内部引用一起丢弃)

我们正在尝试取回这些内存,但是当我们需要处理 WPF 时,要找到仍在引用我们的页面(对象引用)的对象是相当复杂的。

我们已经查看了可视化和逻辑树,并使用分析应用程序来帮助我们手动清理事物(为了证明这个想法),这也被证明是非常困难的。

我坐下来想,为什么我们要做所有这些工作来查找对象引用,我们不能在关闭时“取消引用”这个“页面”吗?

这把我带到了这里:)
非常感谢任何帮助!


更新 1

在评论中,有人问了以下问题:

问:应用程序。真的有记忆问题吗?这些是如何展示/检测的?还是在 GC2 发生之前这段记忆一直存在?– 米奇小麦

A:内存有问题。如果我们离开一个页面(保存页面的属性被设置为一个新对象),旧对象永远不会被垃圾收集器收集。所以记忆只是不断增长。如果我们公司重新开始,请使用此应用程序。我们应该看的第一件事是实现 WeakEvent 模式并在 WPF 中使用更多路由命令。

更新 2

我能够想出自己的解决方案

4

3 回答 3

1

你用过 CLRProfiler 吗?我发现这非常适合查找对象并查找包含对它们的引用的内容。

这个“如何”页面...

http://msdn.microsoft.com/en-us/library/ms979205.aspx

...链接到下载站点。

但是,我认为您的问题的答案是“不”。没有办法说“不再需要对象 foo - 无论它是否已植根,请收集它”。收集有根对象可能会给您的应用程序带来各种不良后果。

于 2009-03-06T15:14:26.827 回答
1

我实现了WeakEvents来解决这个问题。

不幸的是,Microsoft 建议您使用他们的 WeakEventManager 作为基类,并为您的应用程序中的每个事件创建一个管理器类型!!!我试图编写一个继承自这个基础的管理器,并让它更加“通用”(不是在 C# 术语中表示通用)。这种“通用”事件管理器在 Microsoft 的基类中是不可能的。我不得不从头开始编写一个事件管理器。

感谢您对此问题的任何帮助。

于 2009-03-07T18:30:35.800 回答
-1

如果漏洞页面超出范围,包括所有底层数据,GC 将收集它。最终。但是,如果该页面被仍在范围内的任何内容引用,则该页面及其所有数据将保留在内存中,并且 GC 将无法收集它。

据我所知,在修复不良内存管理方面没有简单的按钮。在我看来,这意味着唯一的工作就是清理引用。这将使 GC 更容易收集超出范围的对象。

您可以建议 GC 通过其算法来查看是否可以通过调用 GC.Collect() 来收集任何东西。但是,除非数据确实超出范围,否则除了浪费 CPU 周期外,这几乎没有什么作用。

Phobis 的问题,您的应用程序使用了多少内存?

编辑:

链接到适用于 .net3.5 应用程序的 CLR Profiler 2.0。 https://github.com/MicrosoftArchive/clrprofiler

于 2009-03-06T14:17:11.143 回答