有没有一种好方法来执行 WPF/C# 对象取消引用以进行垃圾收集?

发布于 2024-07-15 04:09:08 字数 1068 浏览 6 评论 0原文

应用程序背景

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

问题

所以,我在一家正在开发一个非常大的软件项目的公司工作。 我们有很多代码发现内存问题。

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

我们无法选择重构每个页面(在此版本中)。 C# 有没有办法删除对象的所有引用? (因此允许垃圾收集器扔掉该对象及其所有内部引用)

我们正在尝试取回该内存,但是当我们有WPF 来处理。

我们查看了视觉树和逻辑树,并使用分析应用程序来帮助我们手动清理内容(以证明这个想法),事实证明这也非常困难。

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

这让我来到这里:)
任何帮助是极大的赞赏!


更新 1

在评论中提出了以下问题:

问: 是否使用该应用程序。 实际上有记忆问题吗? 这些是如何展示/检测的? 或者这段内存会一直保留到 GC2 发生为止? – Mitch Wheat

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

更新2

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

Application Background

Our platform is a click-once WPF application. We have a "shell" that contains a navigation menu structure and it hosts our own custom "page" classes. When you navigate to a new page, we swap out the content of the shell (essentially).

Problem

So, I work for a company that is working on a extremely large software project. We have much code that we found memory issues with.

The problem is that there are plenty of places in our application were events are wired and never unwired. I'm not sure why developers were doing this, I'm guessing that they expected the objects to get cleaned up each time a user navigates to a new "page".

We don't have the option of refactoring every page (in this release). Is there a way with C# to remove all references from an object? (Therefore allowing the garbage collector to throw that object away, along with all of it's internal references)

We are trying to get this memory back, but it is quite complicated to find objects are still referencing our pages (object references), when we have WPF to deal with.

We have looked at the visual and logical trees and used profiling applications to help us to manually clean things up (for proving out the idea) and this proved to be extremely hard as well.

I sat back and thought, why are we doing all this work to find object references, can't we just "dereference" this "page" when it is closed?

Which brings me here :)
Any help is greatly appreciated!


UPDATE 1

In the comments the following was asked:

Q: Does the app. actually have memory problems? How are these exhibited/detected? Or is this memory hanging around until a GC2 happens? – Mitch Wheat

A: It has memory problems. If we leave a page (property that holds the page gets set to a new object) the old object never gets collected by the garbage collector. So memory just keeps on growing. If our company started over, with this application. The first thing we should look at would be implementing WeakEvent Patterns and using more Routed Commands in WPF.

UPDATE 2

I was able to come up with my own solution.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

夏了南城 2024-07-22 04:09:08

你用过CLRProfiler吗? 我发现这非常擅长查找对象以及查找对它们的引用。

此“操作方法”页面...

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

...下载站点的链接。

然而,我认为你的问题的答案是“不”。 没有办法说“不再需要对象 foo - 请收集它,无论它是否具有 root 权限”。 收集有根对象可能会给您的应用程序带来各种不良影响。

Have you used the CLRProfiler? I find this pretty good at finding objects and also finding what holds a reference to them.

This "How To" page...

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

... links to the download site.

However, I think the answer to your question is "no". There isn't a way of saying "object foo is no longer required - collect it please regardless of whether it's rooted or not". Collecting a rooted object could introduce all sorts of badness into your app.

荆棘i 2024-07-22 04:09:08

我实现了 WeakEvents 来解决此问题。

不幸的是,微软建议您使用他们的 WeakEventManager 作为基类,并为应用程序中的每个事件创建一个管理器类型! 我尝试编写一个从该基础继承的管理器,并使其更加“通用”(不是 C# 术语中的通用)。 这种“通用”事件管理器对于 Microsoft 的基类来说是不可能的。 我必须从头开始编写一个事件管理器。

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

I implemented WeakEvents to solve this issue.

Unfortunately, Microsoft recommends that you use their WeakEventManager as a base class and create a manager type for EACH event in your application!!! I tried to write a manager that inherits from this base and get it to be more "generic" (not in the C# term for generic). This "common" Event manager was not possible with Microsoft's base class. I had to write a Event manager from scratch.

Thank you for any help posted to this question.

盗琴音 2024-07-22 04:09:08

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

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

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

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

编辑:

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

If a hole page is going out of scope, including all underlying data, the GC will collect it. Eventually. However if that page is being referenced by anything that is still in scope, the page and all of its data will remain in memory and the GC will not be able to collect it.

As far as I know there is no easy button when it comes to fixing bad memory management. This means the only, in my opinion, is to do the work to clean up references. This will make it easier for the GC to collect objects that are out of scope.

You can suggest to the GC to go through its algorithm to see if anything can be collected by calling GC.Collect(). However this will do very little besides waste CPU cycles unless the data is truly out of scope.

Question for Phobis, How much memory is your application using?

EDIT:

Link to CLR Profiler 2.0 which should work for .net3.5 apps.
https://github.com/MicrosoftArchive/clrprofiler

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文